<!DOCTYPE html><html lang="zh-CN" data-theme="light"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1"><title>React.js框架 + TSX 知识点归纳 | Cyan</title><meta name="author" content="Cyan,843348394@qq.com"><meta name="copyright" content="Cyan"><meta name="format-detection" content="telephone=no"><meta name="theme-color" content="#ffffff"><meta name="description" content="用了几年 Vue，但对于 React 还处在懵懂的状态，趁着最近工作不忙，赶紧把 React 的知识补上 强烈推荐哔哩哔哩上的张天禹老师的教程：尚硅谷React教程（2022加更，B站超火react教程） 有 vue 基础的上手特别快，有需要学习 React 的伙伴可以观看一下    什么是 ReactReact 是一个简单的 javascript UI 库，用于构建高效、快速的用户界面。它是一"><meta property="og:type" content="article"><meta property="og:title" content="React.js框架 + TSX 知识点归纳"><meta property="og:url" content="https://xmwpro.com/post/2b445cd9.html"><meta property="og:site_name" content="Cyan"><meta property="og:description" content="用了几年 Vue，但对于 React 还处在懵懂的状态，趁着最近工作不忙，赶紧把 React 的知识补上 强烈推荐哔哩哔哩上的张天禹老师的教程：尚硅谷React教程（2022加更，B站超火react教程） 有 vue 基础的上手特别快，有需要学习 React 的伙伴可以观看一下    什么是 ReactReact 是一个简单的 javascript UI 库，用于构建高效、快速的用户界面。它是一"><meta property="og:locale" content="zh_CN"><meta property="og:image" content="https://ali-oss.xmwpro.com/global/avatar.jpg"><meta property="article:published_time" content="2022-07-04T17:19:41.000Z"><meta property="article:modified_time" content="2023-06-26T09:26:36.564Z"><meta property="article:author" content="Cyan"><meta property="article:tag" content="React"><meta name="twitter:card" content="summary"><meta name="twitter:image" content="https://ali-oss.xmwpro.com/global/avatar.jpg"><link rel="shortcut icon" href="https://ali-oss.xmwpro.com/global/favicon.ico"><link rel="canonical" href="https://xmwpro.com/post/2b445cd9.html"><link rel="preconnect" href="//cdn.jsdelivr.net"><link rel="preconnect" href="//www.google-analytics.com" crossorigin=""><link rel="preconnect" href="//hm.baidu.com"><meta name="baidu-site-verification" content="codeva-yHszJZWbvj"><link rel="stylesheet" href="/css/index.css"><link rel="stylesheet" href="https://ali-oss.xmwpro.com/cdn/css/all.min.css" media="print" onload='this.media="all"'><link rel="stylesheet" href="https://ali-oss.xmwpro.com/cdn/css/snackbar.min.css" media="print" onload='this.media="all"'><link rel="stylesheet" href="https://ali-oss.xmwpro.com/cdn/css/fancybox.css" media="print" onload='this.media="all"'><script>var _hmt=_hmt||[];!function(){var e=document.createElement("script");e.src="https://hm.baidu.com/hm.js?81fae81fdc8992b3e6ca314f289131e8";var t=document.getElementsByTagName("script")[0];t.parentNode.insertBefore(e,t)}()</script><script async src="https://www.googletagmanager.com/gtag/js?id=G-2P0LMHZNDD"></script><script>function gtag(){dataLayer.push(arguments)}window.dataLayer=window.dataLayer||[],gtag("js",new Date),gtag("config","G-2P0LMHZNDD")</script><script>const GLOBAL_CONFIG={root:"/",algolia:{appId:"2Q4I5JDAJR",apiKey:"2ec9f676fd9c568eb0abedad38d16fe6",indexName:"Hexo",hits:{per_page:6},languages:{input_placeholder:"输入关键词快速查找",hits_empty:"找不到您查询的内容：${query}",hits_stats:"找到 ${hits} 条结果，用时 ${time} 毫秒"}},localSearch:void 0,translate:{defaultEncoding:2,translateDelay:0,msgToTraditionalChinese:"繁",msgToSimplifiedChinese:"簡"},noticeOutdate:void 0,highlight:{plugin:"highlighjs",highlightCopy:!0,highlightLang:!0,highlightHeightLimit:200},copy:{success:"复制成功",error:"复制错误",noSupport:"浏览器不支持"},relativeDate:{homepage:!1,post:!1},runtime:"天",date_suffix:{just:"刚刚",min:"分钟前",hour:"小时前",day:"天前",month:"个月前"},copyright:{limitCount:50,languages:{author:"作者: Cyan",link:"链接: ",source:"来源: Cyan",info:"著作权归作者所有。商业转载请联系作者获得授权，非商业转载请注明出处。"}},lightbox:"fancybox",Snackbar:{chs_to_cht:"你已切换为繁体",cht_to_chs:"你已切换为简体",day_to_night:"你已切换为深色模式",night_to_day:"你已切换为浅色模式",bgLight:"var(--cyan-theme-color)",bgDark:"var(--cyan-theme-color)",position:"top-center"},source:{justifiedGallery:{js:"https://ali-oss.xmwpro.com/cdn/js/fjGallery.min.js",css:"https://ali-oss.xmwpro.com/cdn/css/fjGallery.css"}},isPhotoFigcaption:!0,islazyload:!0,isAnchor:!1,percent:{toc:!1,rightside:!0}}</script><script id="config-diff">var GLOBAL_CONFIG_SITE={title:"React.js框架 + TSX 知识点归纳",isPost:!0,isHome:!1,isHighlightShrink:!1,isToc:!0,postUpdate:"2023-06-26 09:26:36"}</script><noscript><style>#nav{opacity:1}.justified-gallery img{opacity:1}#post-meta time,#recent-posts time{display:inline!important}</style></noscript><script>(e=>{e.saveToLocal={set:function(e,t,o){if(0===o)return;const n=864e5*o,a={value:t,expiry:(new Date).getTime()+n};localStorage.setItem(e,JSON.stringify(a))},get:function(e){const t=localStorage.getItem(e);if(!t)return;const o=JSON.parse(t);if(!((new Date).getTime()>o.expiry))return o.value;localStorage.removeItem(e)}},e.getScript=e=>new Promise(((t,o)=>{const n=document.createElement("script");n.src=e,n.async=!0,n.onerror=o,n.onload=n.onreadystatechange=function(){const e=this.readyState;e&&"loaded"!==e&&"complete"!==e||(n.onload=n.onreadystatechange=null,t())},document.head.appendChild(n)})),e.getCSS=e=>new Promise(((t,o)=>{const n=document.createElement("link");n.rel="stylesheet",n.href=e,n.onload=()=>t(),n.onerror=()=>o(),document.head.appendChild(n)})),e.activateDarkMode=function(){document.documentElement.setAttribute("data-theme","dark"),null!==document.querySelector('meta[name="theme-color"]')&&document.querySelector('meta[name="theme-color"]').setAttribute("content","#0d0d0d")},e.activateLightMode=function(){document.documentElement.setAttribute("data-theme","light"),null!==document.querySelector('meta[name="theme-color"]')&&document.querySelector('meta[name="theme-color"]').setAttribute("content","#ffffff")};const t=saveToLocal.get("theme"),o=(new Date).getHours();void 0===t?o<=6||o>=18?activateDarkMode():activateLightMode():"light"===t?activateLightMode():activateDarkMode();const n=saveToLocal.get("aside-status");void 0!==n&&("hide"===n?document.documentElement.classList.add("hide-aside"):document.documentElement.classList.remove("hide-aside"));/iPad|iPhone|iPod|Macintosh/.test(navigator.userAgent)&&document.documentElement.classList.add("apple")})(window)</script><link rel="stylesheet" href="//at.alicdn.com/t/c/font_3348168_pqjhlyxfz9r.css" media="defer" onload='this.media="all"'><link rel="stylesheet" href="https://ali-oss.xmwpro.com/cdn/css/swiper-bundle.min.css"><link rel="stylesheet" href="https://ali-oss.xmwpro.com/cdn/css/tianli_gpt.css"><script src="https://ali-oss.xmwpro.com/cdn/js/swiper-bundle.min.js"></script><script data-pjax src="https://ali-oss.xmwpro.com/cdn/js/jquery-3.3.1.js"></script><script data-pjax src="https://ali-oss.xmwpro.com/cdn/js/echarts.min.js"></script><script charset="UTF-8" id="LA_COLLECT" src="https://sdk.51.la/js-sdk-pro.min.js"></script><script src="https://ali-oss.xmwpro.com/cdn/js/three.min.js"></script><link rel="stylesheet" href="https://ali-oss.xmwpro.com/cdn/css/font-awesome-animation.min.css" media="defer" onload='this.media="all"'><link rel="stylesheet" href="https://ali-oss.xmwpro.com/cdn/css/tag_plugins.css" media="defer" onload='this.media="all"'><link rel="stylesheet" href="https://ali-oss.xmwpro.com/cdn/css/animate.min.css" media="print" onload='this.media="screen"'><link rel="stylesheet" href="https://ali-oss.xmwpro.com/cdn/css/gitcalendar.css" media="print" onload='this.media="all"'><meta name="generator" content="Hexo 5.4.2"><link rel="alternate" href="/atom.xml" title="Cyan" type="application/atom+xml"></head><body><div id="loading-box" onclick="document.getElementById(&quot;loading-box&quot;).classList.add(&quot;loaded&quot;)"><div class="loading-bg"><div class="loading-img"></div><div class="loading-image-dot"></div></div></div><script>const preloader={endLoading:()=>{document.body.style.overflow="auto",document.getElementById("loading-box").classList.add("loaded")},initLoading:()=>{document.body.style.overflow="",document.getElementById("loading-box").classList.remove("loaded")}};window.addEventListener("load",(()=>{preloader.endLoading()})),document.addEventListener("pjax:send",(()=>{preloader.initLoading()})),document.addEventListener("pjax:complete",(()=>{preloader.endLoading()}))</script><link rel="stylesheet" href="https://ali-oss.xmwpro.com/cdn/css/progress_bar.css"><script src="https://ali-oss.xmwpro.com/cdn/js/pace.min.js"></script><div id="web_bg"></div><div id="music_bg"></div><div id="sidebar"><div id="menu-mask"></div><div id="sidebar-menus"><div class="avatar-img is-center"><img src="" data-lazy-src="https://ali-oss.xmwpro.com/global/avatar.jpg" onerror='onerror=null,src="/img/friend_404.gif"' alt="avatar"></div><div class="sidebar-site-data site-data is-center"><a href="/archives/"><div class="headline">文章</div><div class="length-num">48</div></a><a href="/tags/"><div class="headline">标签</div><div class="length-num">23</div></a><a href="/categories/"><div class="headline">分类</div><div class="length-num">6</div></a></div><hr><div class="menus_items"><div class="menus_item"><a class="site-page group faa-parent animated-hover" href="javascript:void(0);" rel="external nofollow noreferrer"><i class="fa-fw faa-tada fas fa-book"></i> <span>文库</span></a><ul class="menus_item_child"><li><a class="site-page child faa-parent animated-hover" href="/archives/"><i class="fa-fw faa-tada fa-solid fa-box-archive"></i> <span>全部文章</span></a></li><li><a class="site-page child faa-parent animated-hover" href="/tags/"><i class="fa-fw faa-tada fas fa-tags"></i> <span>标签</span></a></li><li><a class="site-page child faa-parent animated-hover" href="/categories/"><i class="fa-fw faa-tada fas fa-shapes"></i> <span>分类</span></a></li></ul></div><div class="menus_item"><a class="site-page group faa-parent animated-hover" href="javascript:void(0);" rel="external nofollow noreferrer"><i class="fa-fw faa-tada fab fa-artstation"></i> <span>社交</span></a><ul class="menus_item_child"><li><a class="site-page child faa-parent animated-hover" href="/link/"><i class="fa-fw faa-tada fa-solid fa-link"></i> <span>友人帐</span></a></li><li><a class="site-page child faa-parent animated-hover" href="/fcircle/"><i class="fa-fw faa-tada fa-solid fa-user-group"></i> <span>朋友圈</span></a></li><li><a class="site-page child faa-parent animated-hover" href="/guestbook/"><i class="fa-fw faa-tada fa-solid fa-envelope"></i> <span>留言板</span></a></li></ul></div><div class="menus_item"><a class="site-page group faa-parent animated-hover" href="javascript:void(0);" rel="external nofollow noreferrer"><i class="fa-fw faa-tada fas fa-coffee"></i> <span>休闲</span></a><ul class="menus_item_child"><li><a class="site-page child faa-parent animated-hover" href="/music/"><i class="fa-fw faa-tada fa-solid fa-music"></i> <span>音乐馆</span></a></li><li><a class="site-page child faa-parent animated-hover" href="/photoAlbum/"><i class="fa-fw faa-tada fa-solid fa-camera"></i> <span>相册</span></a></li><li><a class="site-page child faa-parent animated-hover" href="/essay/"><i class="fa-fw faa-tada fa-solid fa-message"></i> <span>哔哔</span></a></li></ul></div><div class="menus_item"><a class="site-page group faa-parent animated-hover" href="javascript:void(0);" rel="external nofollow noreferrer"><i class="fa-fw faa-tada fa-solid fa-earth-asia"></i> <span>本站</span></a><ul class="menus_item_child"><li><a class="site-page child faa-parent animated-hover" href="/analysis/"><i class="fa-fw faa-tada fa-solid fa-chart-simple"></i> <span>博客统计</span></a></li><li><a class="site-page child faa-parent animated-hover" href="/about/"><i class="fa-fw faa-tada fa-regular fa-address-card"></i> <span>关于我</span></a></li></ul></div></div></div></div><div class="canvas-container" id="canvas"></div><div class="post" id="body-wrap"><header class="post-bg" id="page-header" style="background-image:url('https://ali-oss.xmwpro.com/posts/post_cover33.jpg')"><nav id="nav"><span id="blog-info"><div class="back-home-button" tabindex="-1"><i class="back-home-button-icon fas fa-grip-vertical"></i><div class="back-menu-list-groups"><div class="back-menu-list-group"><div class="back-menu-list-title">社交</div><div class="back-menu-list"><a class="back-menu-item" href="https://xmwpro.com/" title="白雾茫茫丶" target="_blank" one-link-mark="yes"><img class="back-menu-item-icon" src="" data-lazy-src="https://ali-oss.xmwpro.com/global/avatar.jpg"><span class="back-menu-item-text">白雾茫茫丶</span></a><a class="back-menu-item" href="https://github.com/Cyan-Xmw/" rel="external nofollow noreferrer" title="Github" target="_blank" one-link-mark="yes"><i class="iconfont cyan-gitHub"></i><span class="back-menu-item-text">Github</span></a><a class="back-menu-item" href="https://gitee.com/Cyan-Xmw/" rel="external nofollow noreferrer" title="Gitee" target="_blank" one-link-mark="yes"><i class="iconfont cyan-gitee"></i><span class="back-menu-item-text">Gitee</span></a><a class="back-menu-item" href="https://juejin.cn/user/1917147257534279/" rel="external nofollow noreferrer" title="掘金" target="_blank" one-link-mark="yes"><i class="iconfont cyan-juejin"></i><span class="back-menu-item-text">掘金</span></a></div></div><div class="back-menu-list-group"><div class="back-menu-list-title">项目</div><div class="back-menu-list"><a class="back-menu-item" href="https://docs.xmwpro.com/" rel="external nofollow noreferrer" title="Cyan Docs" target="_blank" one-link-mark="yes"><img class="back-menu-item-icon" src="" data-lazy-src="https://ali-oss.xmwpro.com/project/xmw-dumi-docs/logo.svg"><span class="back-menu-item-text">Cyan Docs</span></a><a class="back-menu-item" href="http://react.xmwpro.com/" rel="external nofollow noreferrer" title="Xmw-Admin" target="_blank" one-link-mark="yes"><img class="back-menu-item-icon" src="" data-lazy-src="https://ali-oss.xmwpro.com/pages/resource/xmw-admin.svg"><span class="back-menu-item-text">Xmw-Admin</span></a><a class="back-menu-item" href="http://vue3.xmwpro.com/" rel="external nofollow noreferrer" title="Vue3-Admin" target="_blank" one-link-mark="yes"><img class="back-menu-item-icon" src="" data-lazy-src="https://ali-oss.xmwpro.com/project/vue3-admin/logo.png"><span class="back-menu-item-text">Vue3-Admin</span></a><a class="back-menu-item" href="http://vue2.xmwpro.com/" rel="external nofollow noreferrer" title="Vue2-Admin" target="_blank" one-link-mark="yes"><img class="back-menu-item-icon" src="" data-lazy-src="https://ali-oss.xmwpro.com/project/vue2-admin/logo.svg"><span class="back-menu-item-text">Vue2-Admin</span></a><a class="back-menu-item" href="https://ele-plus-form.xmwpro.com/" rel="external nofollow noreferrer" title="vue3-form" target="_blank" one-link-mark="yes"><img class="back-menu-item-icon" src="" data-lazy-src="https://ali-oss.xmwpro.com/pages/resource/vue.svg"><span class="back-menu-item-text">vue3-form</span></a><a class="back-menu-item" href="https://ele-plus-table.xmwpro.com/" rel="external nofollow noreferrer" title="vue3-table" target="_blank" one-link-mark="yes"><img class="back-menu-item-icon" src="" data-lazy-src="https://ali-oss.xmwpro.com/pages/resource/vue.svg"><span class="back-menu-item-text">vue3-table</span></a></div></div></div></div><a id="site-name" href="/"><div class="title">Cyan</div><i class="fa-solid fa-house"></i></a></span><div id="menus"><div class="menus_items"><div class="menus_item"><a class="site-page group faa-parent animated-hover" href="javascript:void(0);" rel="external nofollow noreferrer"><i class="fa-fw faa-tada fas fa-book"></i> <span>文库</span></a><ul class="menus_item_child"><li><a class="site-page child faa-parent animated-hover" href="/archives/"><i class="fa-fw faa-tada fa-solid fa-box-archive"></i> <span>全部文章</span></a></li><li><a class="site-page child faa-parent animated-hover" href="/tags/"><i class="fa-fw faa-tada fas fa-tags"></i> <span>标签</span></a></li><li><a class="site-page child faa-parent animated-hover" href="/categories/"><i class="fa-fw faa-tada fas fa-shapes"></i> <span>分类</span></a></li></ul></div><div class="menus_item"><a class="site-page group faa-parent animated-hover" href="javascript:void(0);" rel="external nofollow noreferrer"><i class="fa-fw faa-tada fab fa-artstation"></i> <span>社交</span></a><ul class="menus_item_child"><li><a class="site-page child faa-parent animated-hover" href="/link/"><i class="fa-fw faa-tada fa-solid fa-link"></i> <span>友人帐</span></a></li><li><a class="site-page child faa-parent animated-hover" href="/fcircle/"><i class="fa-fw faa-tada fa-solid fa-user-group"></i> <span>朋友圈</span></a></li><li><a class="site-page child faa-parent animated-hover" href="/guestbook/"><i class="fa-fw faa-tada fa-solid fa-envelope"></i> <span>留言板</span></a></li></ul></div><div class="menus_item"><a class="site-page group faa-parent animated-hover" href="javascript:void(0);" rel="external nofollow noreferrer"><i class="fa-fw faa-tada fas fa-coffee"></i> <span>休闲</span></a><ul class="menus_item_child"><li><a class="site-page child faa-parent animated-hover" href="/music/"><i class="fa-fw faa-tada fa-solid fa-music"></i> <span>音乐馆</span></a></li><li><a class="site-page child faa-parent animated-hover" href="/photoAlbum/"><i class="fa-fw faa-tada fa-solid fa-camera"></i> <span>相册</span></a></li><li><a class="site-page child faa-parent animated-hover" href="/essay/"><i class="fa-fw faa-tada fa-solid fa-message"></i> <span>哔哔</span></a></li></ul></div><div class="menus_item"><a class="site-page group faa-parent animated-hover" href="javascript:void(0);" rel="external nofollow noreferrer"><i class="fa-fw faa-tada fa-solid fa-earth-asia"></i> <span>本站</span></a><ul class="menus_item_child"><li><a class="site-page child faa-parent animated-hover" href="/analysis/"><i class="fa-fw faa-tada fa-solid fa-chart-simple"></i> <span>博客统计</span></a></li><li><a class="site-page child faa-parent animated-hover" href="/about/"><i class="fa-fw faa-tada fa-regular fa-address-card"></i> <span>关于我</span></a></li></ul></div></div><center id="name-container"><span id="page-name" href="javascript:void(0);">PAGE_NAME</span></center></div><div id="nav-right"><div class="nav-button" id="search-button"><a class="social-icon search" href="javascript:void(0);" rel="external nofollow noreferrer" title="全局搜索"><i class="fas fa-search fa-fw"></i></a></div><div class="nav-button"><a class="social-icon" target="_blank" rel="noopener external nofollow noreferrer" href="https://travellings.cn/go.html" title="离开这里并访问下一个博客「开往服务」"><i class="fa-solid fa-subway"></i></a></div><div class="nav-button"><a class="social-icon random-post" href="javascript:toRandomPost();" rel="external nofollow noreferrer" title="随机前往一个文章"><i class="fa-solid fa-dice"></i></a></div><div class="nav-button" id="darkmode_navswitch"><a class="darkmode_switchbutton" type="button" title="浅色和深色模式转换" onclick="document.getElementById(&quot;darkmode&quot;).click()"><i class="fas fa-moon isMoon"></i><i class="fas fa-sun isSun"></i></a></div><div class="nav-button" id="go-up" title="回到顶部"><a class="totopbtn" href="javascript:void(0);" rel="external nofollow noreferrer"><span class="scroll-percent" onclick="btf.scrollToDest(0,500)"></span><i class="fas fa-arrow-up" onclick="btf.scrollToDest(0,500)"></i></a></div><div id="toggle-menu"><a class="site-page" href="javascript:void(0);" rel="external nofollow noreferrer"><i class="fas fa-bars fa-fw"></i></a></div></div></nav><div id="post-info"><div class="post-container"><div class="post-container-categories"><a class="categories-link" href="/categories/%E5%89%8D%E7%AB%AF%E5%BC%80%E5%8F%91/">前端开发</a></div><div class="post-container-tags"><a class="tags-link" href="/tags/React/"><span class="tags-punctuation">#</span><span class="tags-name">React</span></a></div></div><h1 class="post-title">React.js框架 + TSX 知识点归纳</h1><div id="post-meta"><div class="meta-secondline"><div class="post-meta-common post-meta-date" title="发表于 2022-07-04 17:19:41"><i class="fas fa-calendar fa-fw post-meta-icon"></i><time class="post-meta-date-created" datetime="2022-07-04T17:19:41.000Z">07-04</time></div><div class="post-meta-common post-meta-date" title="更新于 2023-06-26 09:26:36"><i class="fas fa-history fa-fw post-meta-icon"></i><time class="post-meta-date-updated" datetime="2022-07-04T17:19:41.000Z">06-26</time></div><div class="post-meta-common post-meta-wordcount" title="字数总计 5.5k"><i class="far fa-file-word fa-fw post-meta-icon"></i><span class="word-count">5.5k</span></div><div class="post-meta-common post-meta-read-time" title="阅读时长 22分钟"><i class="far fa-clock fa-fw post-meta-icon"></i><span>22分钟</span></div><div class="post-meta-common post-meta-commentcount" title="评论数" onclick='cyan.scrollTo("#post-comment")'><i class="fa-solid fa-comment fa-fw post-meta-icon"></i><a href="/post/2b445cd9.html#post-comment"><span id="twikoo-count"><i class="fa-solid fa-spinner fa-spin"></i></span></a></div></div></div></div><section class="main-hero-waves-area waves-area"><svg class="waves-svg" xmlns="http://www.w3.org/2000/svg" xlink="http://www.w3.org/1999/xlink" viewBox="0 24 150 28" preserveAspectRatio="none" shape-rendering="auto"><defs><path id="gentle-wave" d="M-160 44c30 0 58-18 88-18s58 18 88 18 58-18 88-18 58 18 88 18v44h-352Z"></path></defs><g class="parallax"><use href="#gentle-wave" x="48" y="0"></use><use href="#gentle-wave" x="48" y="3"></use><use href="#gentle-wave" x="48" y="5"></use><use href="#gentle-wave" x="48" y="7"></use></g></svg></section></header><main class="layout" id="content-inner"><div id="post"><article class="post-content" id="article-container"><div class="tip theme fa-house"><ol><li>用了几年 Vue，但对于 React 还处在懵懂的状态，趁着最近工作不忙，赶紧把 React 的知识补上</li><li>强烈推荐哔哩哔哩上的张天禹老师的教程：<a target="_blank" rel="noopener external nofollow noreferrer" href="https://www.bilibili.com/video/BV1wy4y1D7JT?spm_id_from=333.337.search-card.all.click">尚硅谷React教程（2022加更，B站超火react教程）</a></li><li>有 vue 基础的上手特别快，有需要学习 React 的伙伴可以观看一下</li></ol></div><h2 id="什么是-React"><a href="#什么是-React" class="headerlink" title="什么是 React"></a>什么是 React</h2><p>React 是一个简单的 javascript UI 库，用于构建高效、快速的用户界面。它是一个轻量级库，因此很受欢迎。它遵循组件设计模式、声明式编程范式和函数式编程概念，以使前端应用程序更高效。它使用 虚拟DOM 来有效地操作 DOM。它遵循从高阶组件到低阶组件的单向数据流。</p><h2 id="React-和-Vue-的区别"><a href="#React-和-Vue-的区别" class="headerlink" title="React 和  Vue 的区别"></a>React 和 Vue 的区别</h2><h3 id="核心思想不同"><a href="#核心思想不同" class="headerlink" title="核心思想不同"></a>核心思想不同</h3><ol><li>Vue 的核心思想是尽可能的降低前端开发的门槛，是一个灵活易用的渐进式双向绑定的 MVVM 框架。</li><li>React 的核心思想是声明式渲染和组件化、单向数据流，React 既不属于 MVC 也不属于 MVVM 架构。</li></ol><h4 id="声明式是什么意思？"><a href="#声明式是什么意思？" class="headerlink" title="声明式是什么意思？"></a>声明式是什么意思？</h4><div class="note flat info simple"><p>声明式与之相对应的是命令式，命令式指的是通过DOM操作一步步把网页变成想要的样子，而声明式则是只需要通过状态去形容最后的网页长什么样子即可。</p></div><h4 id="组件化是什么意思？"><a href="#组件化是什么意思？" class="headerlink" title="组件化是什么意思？"></a>组件化是什么意思？</h4><div class="note flat info simple"><p>组件化指的是尽可能的将页面拆分成一个个较小的、可以复用的组件，这样让我们的代码更加方便组织和管理，并且拓展性页更强。</p></div><h4 id="如何理解React的单向数据流？"><a href="#如何理解React的单向数据流？" class="headerlink" title="如何理解React的单向数据流？"></a>如何理解React的单向数据流？</h4><div class="note flat info simple"><p>React 的单向数据流指的是数据主要从父节点通过 props 传递到子节点，如果顶层某个 props 改变了，React 会重新渲染所有的子节点，但是单向数据流并非单向绑定，React 想要从一个组件去更新另一个组件的状态，需要进行状态提升，即将状态提升到他们最近的祖先组件中，触发父组件的状态变更，从而影响另一个组件的显示。单向数据流的好处是能够保证状态改变的可追溯性，假如，父组件维护了一个状态，子组件如果能够随意更改父组件的状态，那么各组件的状态改变就会变得难以追溯。</p></div><h3 id="组件写法上不同"><a href="#组件写法上不同" class="headerlink" title="组件写法上不同"></a>组件写法上不同</h3><ol><li>Vue 的组件写法是通过 template 的单文件组件格式。</li><li>React 的组件写法是 JSX+inline style，也就是吧 HTML 和 CSS 全部写进 JavaScript 中。</li></ol><h3 id="diff-算法不同"><a href="#diff-算法不同" class="headerlink" title="diff 算法不同"></a>diff 算法不同</h3><ol><li>vue 对比节点，如果节点元素类型相同，但是 className 不同，认为是不同类型的元素，会进行删除重建，但是 react 则会认为是同类型的节点，只会修改节点属性。</li><li>vue 的列表比对采用的是首尾指针法，而 react 采用的是从左到右依次比对的方式，当一个集合只是把最后一个节点移动到了第一个，react 会把前面的节点依次移动，而 vue 只会把最后一个节点移动到最后一个，从这点上来说 vue 的对比方式更加高效。</li></ol><h3 id="响应式原理不同"><a href="#响应式原理不同" class="headerlink" title="响应式原理不同"></a>响应式原理不同</h3><ol><li>React 主要是通过 setState() 方法来更新状态，状态更新之后，组件也会重新渲染。</li><li>vue 会遍历 data 数据对象，使用 Object.definedProperty() 将每个属性都转换为 getter 和 setter，每个 Vue组件实例 都有一个对应的 watcher 实例，在组件初次渲染的时候会记录组件用到了那些数据，当数据发生改变的时候，会触发 setter 方法，并通知所有依赖这个数据的 watcher 实例调用 update 方法去触发组件的 compile 渲染方法，进行渲染数据。</li></ol><h2 id="什么是-JSX-？"><a href="#什么是-JSX-？" class="headerlink" title="什么是 JSX ？"></a>什么是 JSX ？</h2><p>JSX 是 javascript 的语法扩展。它就像一个拥有 javascript 全部功能的模板语言。它生成 React 元素，这些元素将在 DOM中 呈现。React 建议在组件使用 JSX。在 JSX 中，我们结合了 javascript 和 HTML，并生成了可以在 DOM中 呈现的 react 元素。</p><h2 id="函数式组件和类组件"><a href="#函数式组件和类组件" class="headerlink" title="函数式组件和类组件"></a>函数式组件和类组件</h2><h3 id="什么是函数式组件-无状态"><a href="#什么是函数式组件-无状态" class="headerlink" title="什么是函数式组件(无状态)"></a>什么是函数式组件(无状态)</h3><div class="note flat info simple"><p>函数或无状态组件是一个纯函数，它可接受接受参数，并返回 react 元素。这些都是没有任何副作用的纯函数。这些组件没有状态或生命周期方法</p></div><figure class="highlight typescript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> &#123; <span class="variable constant_">FC</span> &#125; <span class="keyword">from</span> <span class="string">&#x27;react&#x27;</span>; <span class="comment">// 其中 FC 是 FunctionComponent 的缩写</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> <span class="title class_">App</span>: <span class="variable constant_">FC</span> = <span class="function">() =&gt;</span> &#123;</span><br><span class="line">  <span class="keyword">return</span> <span class="language-xml"><span class="tag">&lt;<span class="name">h1</span>&gt;</span>Holle React!<span class="tag">&lt;/<span class="name">h1</span>&gt;</span></span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="什么是类组件-有状态"><a href="#什么是类组件-有状态" class="headerlink" title="什么是类组件(有状态)"></a>什么是类组件(有状态)</h3><div class="note flat info simple"><p>类或有状态组件具有状态和生命周期方可能通过 setState() 方法更改组件的状态。类组件是通过扩展 React 创建的。它在构造函数中初始化，也可能有子组件。</p></div><figure class="highlight typescript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> &#123; <span class="title class_">Component</span> &#125; <span class="keyword">from</span> <span class="string">&#x27;react&#x27;</span>;</span><br><span class="line"></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> <span class="keyword">class</span> <span class="title class_">App</span> <span class="keyword">extends</span> <span class="title class_ inherited__">Component</span> &#123;</span><br><span class="line">  <span class="title function_">render</span>(<span class="params"></span>) &#123;</span><br><span class="line">    <span class="keyword">return</span> <span class="language-xml"><span class="tag">&lt;<span class="name">h1</span>&gt;</span>Holle React!<span class="tag">&lt;/<span class="name">h1</span>&gt;</span></span></span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h2 id="组件三大核心属性之一-State"><a href="#组件三大核心属性之一-State" class="headerlink" title="组件三大核心属性之一: State"></a>组件三大核心属性之一: State</h2><div class="note flat info simple"><ol><li>state 是 React 组件对象中最重要的属性，值是对象（可以包含多个key-value的组合）。</li><li>组件被称为状态机，通过更新组件中的 state 来更新对应的页面显示（重新渲染组件）。</li><li>我们可以理解为 Vue 中的 data。</li><li>state 不能直接更改，要通过 setState() 方法更改组件的状态。</li></ol></div><h3 id="初始化-state"><a href="#初始化-state" class="headerlink" title="初始化 state"></a>初始化 state</h3><figure class="highlight typescript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> &#123; <span class="title class_">Component</span> &#125; <span class="keyword">from</span> <span class="string">&#x27;react&#x27;</span>;</span><br><span class="line"></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> <span class="keyword">class</span> <span class="title class_">App</span> <span class="keyword">extends</span> <span class="title class_ inherited__">Component</span>&lt;<span class="built_in">any</span>,<span class="built_in">any</span>&gt; &#123;</span><br><span class="line">  <span class="comment">// 如果声明了 constructor，此处必须使用super接收props。</span></span><br><span class="line">  <span class="title function_">constructor</span>(<span class="params">props:<span class="built_in">any</span></span>)&#123;</span><br><span class="line">    <span class="variable language_">super</span>(props)</span><br><span class="line">    <span class="variable language_">this</span>.<span class="property">state</span> = &#123;<span class="attr">name</span>:<span class="string">&#x27;React&#x27;</span>&#125;</span><br><span class="line">  &#125;</span><br><span class="line">  <span class="comment">// 如果不声明 constructor</span></span><br><span class="line">  <span class="comment">// state = &#123;name:&#x27;React&#x27;&#125;</span></span><br><span class="line"></span><br><span class="line">  <span class="title function_">render</span>(<span class="params"></span>) &#123;</span><br><span class="line">    <span class="keyword">return</span> <span class="language-xml"><span class="tag">&lt;<span class="name">h1</span>&gt;</span>Holle &#123;this.state.name&#125;!<span class="tag">&lt;/<span class="name">h1</span>&gt;</span></span></span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="事件绑定和更改-State-状态"><a href="#事件绑定和更改-State-状态" class="headerlink" title="事件绑定和更改 State 状态"></a>事件绑定和更改 State 状态</h3><figure class="highlight typescript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> &#123; <span class="title class_">Component</span> &#125; <span class="keyword">from</span> <span class="string">&#x27;react&#x27;</span>;</span><br><span class="line"></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> <span class="keyword">class</span> <span class="title class_">App</span> <span class="keyword">extends</span> <span class="title class_ inherited__">Component</span>&lt;<span class="built_in">any</span>,<span class="built_in">any</span>&gt; &#123;</span><br><span class="line">  <span class="comment">// 如果声明了 constructor，此处必须使用super接收props。</span></span><br><span class="line">  <span class="title function_">constructor</span>(<span class="params">props:<span class="built_in">any</span></span>)&#123;</span><br><span class="line">    <span class="variable language_">super</span>(props)</span><br><span class="line">    <span class="variable language_">this</span>.<span class="property">state</span> = &#123;<span class="attr">name</span>:<span class="string">&#x27;React&#x27;</span>&#125;</span><br><span class="line">  &#125;</span><br><span class="line">  <span class="comment">// 如果不声明 constructor</span></span><br><span class="line">  state = &#123;<span class="attr">name</span>:<span class="string">&#x27;React&#x27;</span>&#125;</span><br><span class="line"></span><br><span class="line">  <span class="comment">// 此处必须要用箭头函数，让this指向外层也就是 APP 的实例，如果直接写changeState()，this会是undefined</span></span><br><span class="line">  changeState = <span class="function">() =&gt;</span>&#123;</span><br><span class="line">    <span class="comment">// 错误写法</span></span><br><span class="line">    <span class="variable language_">this</span>.<span class="property">state</span>.<span class="property">name</span> = <span class="string">&#x27;Vue&#x27;</span></span><br><span class="line">    <span class="comment">// 正确写法</span></span><br><span class="line">    <span class="variable language_">this</span>.<span class="title function_">setState</span>(&#123;<span class="attr">name</span>:<span class="string">&#x27;Vue&#x27;</span>&#125;)</span><br><span class="line">  &#125;</span><br><span class="line"></span><br><span class="line">  <span class="comment">// 如果需要传参</span></span><br><span class="line">  changeState = <span class="function">(<span class="params">data</span>) =&gt;</span>&#123;</span><br><span class="line">    </span><br><span class="line">  &#125;</span><br><span class="line"></span><br><span class="line">  <span class="title function_">render</span>(<span class="params"></span>) &#123;</span><br><span class="line">    <span class="comment">// 不需传参，事件不要加上小括号()，事件回调是一个函数，不然就要写成箭头函数的形式</span></span><br><span class="line">    <span class="comment">// &lt;h1 onClick=&#123;(e)=&gt;this.changeState(e)&#125;&gt;Holle &#123;this.state.name&#125;!&lt;/h1&gt;</span></span><br><span class="line">    <span class="keyword">return</span> <span class="language-xml"><span class="tag">&lt;<span class="name">h1</span> <span class="attr">onClick</span>=<span class="string">&#123;this.changeState&#125;</span>&gt;</span>Holle &#123;this.state.name&#125;!<span class="tag">&lt;/<span class="name">h1</span>&gt;</span></span></span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><div class="note flat info simple"><ol><li>state 的状态不能直接改变，需要通过 setState() 方法去更改</li><li>事件绑定名称需要使用驼峰法，例如：onClick、onChange、onBlur等</li><li>事件的回调是一个函数，事件的方法要写成箭头函数的形式，让 this 指向类的实例</li></ol></div><h2 id="组件三大核心属性之一-Props"><a href="#组件三大核心属性之一-Props" class="headerlink" title="组件三大核心属性之一: Props"></a>组件三大核心属性之一: Props</h2><div class="note flat info simple"><ol><li>Props 是只读属性，传递给组件以呈现UI和状态。</li></ol></div><figure class="highlight typescript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> &#123; <span class="title class_">Component</span> &#125; <span class="keyword">from</span> <span class="string">&#x27;react&#x27;</span>;</span><br><span class="line"></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">Parent</span> <span class="keyword">extends</span> <span class="title class_ inherited__">Component</span>&lt;<span class="built_in">any</span>,<span class="built_in">any</span>&gt; &#123;</span><br><span class="line">  state = &#123;<span class="attr">name</span>:<span class="string">&#x27;我是子组件&#x27;</span>&#125;</span><br><span class="line">  <span class="title function_">render</span>(<span class="params"></span>) &#123;</span><br><span class="line">    <span class="keyword">const</span> &#123; name &#125; = <span class="variable language_">this</span>.<span class="property">state</span></span><br><span class="line">    <span class="keyword">return</span> (</span><br><span class="line">      <span class="language-xml"><span class="tag">&lt;<span class="name">h1</span>&gt;</span>Holle React!<span class="tag">&lt;/<span class="name">h1</span>&gt;</span></span></span><br><span class="line">      <span class="language-xml"><span class="tag">&lt;<span class="name">Child</span> <span class="attr">name</span>=<span class="string">&#123;name&#125;</span> /&gt;</span></span></span><br><span class="line">    )</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">Child</span> <span class="keyword">extends</span> <span class="title class_ inherited__">Component</span>&lt;<span class="built_in">any</span>,<span class="built_in">any</span>&gt; &#123;</span><br><span class="line">  <span class="title function_">render</span>(<span class="params"></span>) &#123;</span><br><span class="line">    <span class="keyword">const</span> &#123; name &#125; = <span class="variable language_">this</span>.<span class="property">props</span></span><br><span class="line">    <span class="keyword">return</span> <span class="language-xml"><span class="tag">&lt;<span class="name">h1</span>&gt;</span>Holle &#123;name&#125;!<span class="tag">&lt;/<span class="name">h1</span>&gt;</span></span></span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p><img src="" data-lazy-src="https://s2.loli.net/2022/07/05/FR8kPbpV7EjnfzX.jpg" alt="1656987724187.jpg"></p><h3 id="PropTypes-为组件提供类型检查"><a href="#PropTypes-为组件提供类型检查" class="headerlink" title="PropTypes 为组件提供类型检查"></a>PropTypes 为组件提供类型检查</h3><p>参考文档<a target="_blank" rel="noopener external nofollow noreferrer" href="https://zh-hans.reactjs.org/docs/typechecking-with-proptypes.html#gatsby-focus-wrapper">使用 PropTypes 进行类型检查</a><br></p><figure class="highlight typescript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> &#123; <span class="title class_">Component</span> &#125; <span class="keyword">from</span> <span class="string">&#x27;react&#x27;</span>;</span><br><span class="line"><span class="keyword">import</span> <span class="title class_">PropTypes</span> <span class="keyword">from</span> <span class="string">&#x27;prop-types&#x27;</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">Parent</span> <span class="keyword">extends</span> <span class="title class_ inherited__">Component</span>&lt;<span class="built_in">any</span>,<span class="built_in">any</span>&gt; &#123;</span><br><span class="line">  state = &#123;<span class="attr">name</span>:<span class="string">&#x27;我是子组件&#x27;</span>&#125;</span><br><span class="line">  <span class="title function_">render</span>(<span class="params"></span>) &#123;</span><br><span class="line">    <span class="keyword">const</span> &#123; name &#125; = <span class="variable language_">this</span>.<span class="property">state</span></span><br><span class="line">    <span class="keyword">return</span> (</span><br><span class="line">      <span class="language-xml"><span class="tag">&lt;<span class="name">h1</span>&gt;</span>Holle React!<span class="tag">&lt;/<span class="name">h1</span>&gt;</span></span></span><br><span class="line">      <span class="language-xml"><span class="tag">&lt;<span class="name">Child</span> <span class="attr">name</span>=<span class="string">&#123;name&#125;</span> /&gt;</span></span></span><br><span class="line">    )</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">Child</span> <span class="keyword">extends</span> <span class="title class_ inherited__">Component</span>&lt;<span class="built_in">any</span>,<span class="built_in">any</span>&gt; &#123;</span><br><span class="line">  <span class="comment">// 静态类型检查写法，也可使用Child.propTypes写在外部</span></span><br><span class="line">  <span class="comment">// 规定 props 类型</span></span><br><span class="line">  <span class="keyword">static</span> propTypes = &#123;</span><br><span class="line">    <span class="attr">name</span>:<span class="title class_">PropTypes</span>.<span class="property">string</span>.<span class="property">isRequired</span></span><br><span class="line">    <span class="comment">/* 你可以将属性声明为 JS 原生类型，默认情况下</span></span><br><span class="line"><span class="comment">    这些属性都是可选的。</span></span><br><span class="line"><span class="comment">    optionalArray: PropTypes.array,</span></span><br><span class="line"><span class="comment">    optionalBool: PropTypes.bool,</span></span><br><span class="line"><span class="comment">    optionalFunc: PropTypes.func,</span></span><br><span class="line"><span class="comment">    optionalNumber: PropTypes.number,</span></span><br><span class="line"><span class="comment">    optionalObject: PropTypes.object,</span></span><br><span class="line"><span class="comment">    optionalString: PropTypes.string,</span></span><br><span class="line"><span class="comment">    optionalSymbol: PropTypes.symbol,</span></span><br><span class="line"><span class="comment"></span></span><br><span class="line"><span class="comment">    // 任何可被渲染的元素（包括数字、字符串、元素或数组）</span></span><br><span class="line"><span class="comment">    // (或 Fragment) 也包含这些类型。</span></span><br><span class="line"><span class="comment">    optionalNode: PropTypes.node,</span></span><br><span class="line"><span class="comment"></span></span><br><span class="line"><span class="comment">    // 一个 React 元素。</span></span><br><span class="line"><span class="comment">    optionalElement: PropTypes.element,</span></span><br><span class="line"><span class="comment"></span></span><br><span class="line"><span class="comment">    // 一个 React 元素类型（即，MyComponent）。</span></span><br><span class="line"><span class="comment">    optionalElementType: PropTypes.elementType,</span></span><br><span class="line"><span class="comment"></span></span><br><span class="line"><span class="comment">    // 你也可以声明 prop 为类的实例，这里使用</span></span><br><span class="line"><span class="comment">    // JS 的 instanceof 操作符。</span></span><br><span class="line"><span class="comment">    optionalMessage: PropTypes.instanceOf(Message),</span></span><br><span class="line"><span class="comment"></span></span><br><span class="line"><span class="comment">    // 你可以让你的 prop 只能是特定的值，指定它为</span></span><br><span class="line"><span class="comment">    // 枚举类型。</span></span><br><span class="line"><span class="comment">    optionalEnum: PropTypes.oneOf([&#x27;News&#x27;, &#x27;Photos&#x27;]),</span></span><br><span class="line"><span class="comment"></span></span><br><span class="line"><span class="comment">    // 一个对象可以是几种类型中的任意一个类型</span></span><br><span class="line"><span class="comment">    optionalUnion: PropTypes.oneOfType([</span></span><br><span class="line"><span class="comment">      PropTypes.string,</span></span><br><span class="line"><span class="comment">      PropTypes.number,</span></span><br><span class="line"><span class="comment">      PropTypes.instanceOf(Message)</span></span><br><span class="line"><span class="comment">    ]),</span></span><br><span class="line"><span class="comment"></span></span><br><span class="line"><span class="comment">    // 可以指定一个数组由某一类型的元素组成</span></span><br><span class="line"><span class="comment">    optionalArrayOf: PropTypes.arrayOf(PropTypes.number),</span></span><br><span class="line"><span class="comment"></span></span><br><span class="line"><span class="comment">    // 可以指定一个对象由某一类型的值组成</span></span><br><span class="line"><span class="comment">    optionalObjectOf: PropTypes.objectOf(PropTypes.number),</span></span><br><span class="line"><span class="comment"></span></span><br><span class="line"><span class="comment">    // 可以指定一个对象由特定的类型值组成</span></span><br><span class="line"><span class="comment">    optionalObjectWithShape: PropTypes.shape(&#123;</span></span><br><span class="line"><span class="comment">      color: PropTypes.string,</span></span><br><span class="line"><span class="comment">      fontSize: PropTypes.number</span></span><br><span class="line"><span class="comment">    &#125;),</span></span><br><span class="line"><span class="comment"></span></span><br><span class="line"><span class="comment">    // An object with warnings on extra properties</span></span><br><span class="line"><span class="comment">    optionalObjectWithStrictShape: PropTypes.exact(&#123;</span></span><br><span class="line"><span class="comment">      name: PropTypes.string,</span></span><br><span class="line"><span class="comment">      quantity: PropTypes.number</span></span><br><span class="line"><span class="comment">    &#125;),</span></span><br><span class="line"><span class="comment"></span></span><br><span class="line"><span class="comment">    // 你可以在任何 PropTypes 属性后面加上 `isRequired` ，确保</span></span><br><span class="line"><span class="comment">    // 这个 prop 没有被提供时，会打印警告信息。</span></span><br><span class="line"><span class="comment">    requiredFunc: PropTypes.func.isRequired,</span></span><br><span class="line"><span class="comment"></span></span><br><span class="line"><span class="comment">    // 任意类型的必需数据</span></span><br><span class="line"><span class="comment">    requiredAny: PropTypes.any.isRequired,</span></span><br><span class="line"><span class="comment"></span></span><br><span class="line"><span class="comment">    // 你可以指定一个自定义验证器。它在验证失败时应返回一个 Error 对象。</span></span><br><span class="line"><span class="comment">    // 请不要使用 `console.warn` 或抛出异常，因为这在 `oneOfType` 中不会起作用。</span></span><br><span class="line"><span class="comment">    customProp: function(props, propName, componentName) &#123;</span></span><br><span class="line"><span class="comment">      if (!/matchme/.test(props[propName])) &#123;</span></span><br><span class="line"><span class="comment">        return new Error(</span></span><br><span class="line"><span class="comment">          &#x27;Invalid prop `&#x27; + propName + &#x27;` supplied to&#x27; +</span></span><br><span class="line"><span class="comment">          &#x27; `&#x27; + componentName + &#x27;`. Validation failed.&#x27;</span></span><br><span class="line"><span class="comment">        );</span></span><br><span class="line"><span class="comment">      &#125;</span></span><br><span class="line"><span class="comment">    &#125;,</span></span><br><span class="line"><span class="comment"></span></span><br><span class="line"><span class="comment">    // 你也可以提供一个自定义的 `arrayOf` 或 `objectOf` 验证器。</span></span><br><span class="line"><span class="comment">    // 它应该在验证失败时返回一个 Error 对象。</span></span><br><span class="line"><span class="comment">    // 验证器将验证数组或对象中的每个值。验证器的前两个参数</span></span><br><span class="line"><span class="comment">    // 第一个是数组或对象本身</span></span><br><span class="line"><span class="comment">    // 第二个是他们当前的键。</span></span><br><span class="line"><span class="comment">    customArrayProp: PropTypes.arrayOf(function(propValue, key, componentName, location, propFullName) &#123;</span></span><br><span class="line"><span class="comment">      if (!/matchme/.test(propValue[key])) &#123;</span></span><br><span class="line"><span class="comment">        return new Error(</span></span><br><span class="line"><span class="comment">          &#x27;Invalid prop `&#x27; + propFullName + &#x27;` supplied to&#x27; +</span></span><br><span class="line"><span class="comment">          &#x27; `&#x27; + componentName + &#x27;`. Validation failed.&#x27;</span></span><br><span class="line"><span class="comment">        );</span></span><br><span class="line"><span class="comment">      &#125;</span></span><br><span class="line"><span class="comment">    &#125;) */</span></span><br><span class="line">  &#125;</span><br><span class="line">  <span class="comment">// 规定 props 默认值</span></span><br><span class="line">  <span class="keyword">static</span> defaultProps = &#123;</span><br><span class="line">    <span class="attr">name</span>: <span class="string">&#x27;Hello React!&#x27;</span></span><br><span class="line">  &#125;</span><br><span class="line">  <span class="title function_">render</span>(<span class="params"></span>) &#123;</span><br><span class="line">    <span class="keyword">const</span> &#123; name &#125; = <span class="variable language_">this</span>.<span class="property">props</span></span><br><span class="line">    <span class="keyword">return</span> <span class="language-xml"><span class="tag">&lt;<span class="name">h1</span>&gt;</span>Holle &#123;name&#125;!<span class="tag">&lt;/<span class="name">h1</span>&gt;</span></span></span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p></p><h2 id="组件三大核心属性之一-Refs"><a href="#组件三大核心属性之一-Refs" class="headerlink" title="组件三大核心属性之一: Refs"></a>组件三大核心属性之一: Refs</h2><h3 id="何时使用-Refs"><a href="#何时使用-Refs" class="headerlink" title="何时使用 Refs"></a>何时使用 Refs</h3><ol><li>管理焦点，文本选择或媒体播放。</li><li>触发强制动画。</li><li>集成第三方 DOM 库。</li></ol><h3 id="创建-Refs"><a href="#创建-Refs" class="headerlink" title="创建 Refs"></a>创建 Refs</h3><ol><li><p>使用 React.createRef() 创建</p><figure class="highlight typescript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> <span class="title class_">React</span>,&#123; <span class="title class_">Component</span> &#125; <span class="keyword">from</span> <span class="string">&#x27;react&#x27;</span>;</span><br><span class="line"></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> <span class="keyword">class</span> <span class="title class_">App</span> <span class="keyword">extends</span> <span class="title class_ inherited__">Component</span>&lt;<span class="built_in">any</span>,<span class="built_in">any</span>&gt; &#123;</span><br><span class="line">  <span class="comment">// 创建 Refs</span></span><br><span class="line">  textInput = <span class="title class_">React</span>.<span class="title function_">createRef</span>()</span><br><span class="line">  focusTextInput = <span class="function">() =&gt;</span> &#123;</span><br><span class="line">    <span class="comment">// 直接使用原生 API 使 text 输入框获得焦点</span></span><br><span class="line">    <span class="comment">// 注意：我们通过 &quot;current&quot; 来访问 DOM 节点</span></span><br><span class="line">    <span class="variable language_">this</span>.<span class="property">textInput</span>.<span class="property">current</span>.<span class="title function_">focus</span>();</span><br><span class="line">  &#125;</span><br><span class="line">  <span class="title function_">render</span>(<span class="params"></span>) &#123;</span><br><span class="line">    <span class="keyword">return</span> (</span><br><span class="line">      <span class="language-xml"><span class="tag">&lt;<span class="name">div</span>&gt;</span></span></span><br><span class="line"><span class="language-xml">        <span class="tag">&lt;<span class="name">h1</span> <span class="attr">onClick</span>=<span class="string">&#123;this.focusTextInput&#125;</span>&gt;</span>Holle React!<span class="tag">&lt;/<span class="name">h1</span>&gt;</span></span></span><br><span class="line"><span class="language-xml">        <span class="tag">&lt;<span class="name">input</span> <span class="attr">type</span>=<span class="string">&quot;text&quot;</span> <span class="attr">ref</span>=<span class="string">&#123;this.textInput&#125;/</span>&gt;</span></span></span><br><span class="line"><span class="language-xml">      <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span></span><br><span class="line">    )</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></li><li><p>回调 Refs</p><figure class="highlight typescript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> &#123; <span class="title class_">Component</span> &#125; <span class="keyword">from</span> <span class="string">&#x27;react&#x27;</span>;</span><br><span class="line"></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> <span class="keyword">class</span> <span class="title class_">App</span> <span class="keyword">extends</span> <span class="title class_ inherited__">Component</span>&lt;<span class="built_in">any</span>,<span class="built_in">any</span>&gt; &#123;</span><br><span class="line">  <span class="comment">// 创建 Refs</span></span><br><span class="line">  textInput = <span class="literal">null</span></span><br><span class="line">  setTextInputRef = <span class="function">(<span class="params">e</span>) =&gt;</span> &#123;</span><br><span class="line">    <span class="comment">// 绑定 Refs</span></span><br><span class="line">    <span class="variable language_">this</span>.<span class="property">textInput</span> = e</span><br><span class="line">  &#125;</span><br><span class="line">  <span class="title function_">componentDidMount</span>(<span class="params"></span>)&#123;</span><br><span class="line">    <span class="comment">// 组件挂载后，让文本框自动获得焦点</span></span><br><span class="line">    <span class="variable language_">this</span>.<span class="property">textInput</span> &amp;&amp; <span class="variable language_">this</span>.<span class="property">textInput</span>.<span class="title function_">focus</span>()</span><br><span class="line">  &#125;</span><br><span class="line">  <span class="title function_">render</span>(<span class="params"></span>) &#123;</span><br><span class="line">    <span class="keyword">return</span> <span class="language-xml"><span class="tag">&lt;<span class="name">input</span> <span class="attr">type</span>=<span class="string">&quot;text&quot;</span> <span class="attr">ref</span>=<span class="string">&#123;this.setTextInputRef&#125;/</span>&gt;</span></span></span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></li><li><p>过时 API: String Refs</p><figure class="highlight typescript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> &#123; <span class="title class_">Component</span> &#125; <span class="keyword">from</span> <span class="string">&#x27;react&#x27;</span>;</span><br><span class="line"></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> <span class="keyword">class</span> <span class="title class_">App</span> <span class="keyword">extends</span> <span class="title class_ inherited__">Component</span>&lt;<span class="built_in">any</span>,<span class="built_in">any</span>&gt; &#123;</span><br><span class="line">  <span class="title function_">componentDidMount</span>(<span class="params"></span>)&#123;</span><br><span class="line">    <span class="comment">// 组件挂载后，让文本框自动获得焦点</span></span><br><span class="line">    <span class="variable language_">this</span>.<span class="property">refs</span>.<span class="property">textInput</span>.<span class="title function_">focus</span>()</span><br><span class="line">  &#125;</span><br><span class="line">  <span class="title function_">render</span>(<span class="params"></span>) &#123;</span><br><span class="line">    <span class="keyword">return</span> <span class="language-xml"><span class="tag">&lt;<span class="name">input</span> <span class="attr">type</span>=<span class="string">&quot;text&quot;</span> <span class="attr">ref</span>=<span class="string">&quot;textInput&quot;</span>/&gt;</span></span></span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><div class="note flat warning simple"><p>如果你目前还在使用 this.refs.textInput 这种方式访问 refs ，我们建议用<a target="_blank" rel="noopener external nofollow noreferrer" href="https://zh-hans.reactjs.org/docs/refs-and-the-dom.html#callback-refs">回调函数</a>或 <a target="_blank" rel="noopener external nofollow noreferrer" href="https://zh-hans.reactjs.org/docs/refs-and-the-dom.html#creating-refs">createRef API</a> 的方式代替。</p></div></li></ol><h2 id="React-生命周期"><a href="#React-生命周期" class="headerlink" title="React 生命周期"></a>React 生命周期</h2><h3 id="什么是生命周期"><a href="#什么是生命周期" class="headerlink" title="什么是生命周期?"></a>什么是生命周期?</h3><div class="note flat info simple"><ol><li>生命周期就是组件从挂载到销毁的一个过程，每个特定的阶段都会有对应的 API 去完成对应的操作</li><li>React 组件的生命周期可以分为3个状态:<ul><li>Mounting(挂载)：已插入真实 DOM</li><li>Updating(更新)：正在被重新渲染</li><li>Unmounting(卸载)：已移出真实 DOM</li></ul></li></ol></div><p><img src="" data-lazy-src="https://s2.loli.net/2022/07/05/VMd8fKJrOcSL6QZ.webp" alt="src_http___upload-images.jianshu.io_upload_images_5098241-10770cb6c6743070.png_refer_http___upload-images.jianshu.webp"></p><h3 id="Mounting-挂载"><a href="#Mounting-挂载" class="headerlink" title="Mounting(挂载)"></a>Mounting(挂载)</h3><p>当组件实例被创建并插入 DOM 中时，其生命周期调用顺序如下：</p><ul><li>constructor(): 在 React 组件挂载之前，会调用它的构造函数。</li><li>getDerivedStateFromProps(): 在调用 render 方法之前调用，并且在初始挂载及后续更新时都会被调用。</li><li>render(): render() 方法是 class 组件中唯一必须实现的方法。</li><li>componentDidMount(): 在组件挂载后（插入 DOM 树中）立即调用。<br>render() 方法是 class 组件中唯一必须实现的方法，其他方法可以根据自己的需要来实现。</li></ul><h3 id="Updating-更新"><a href="#Updating-更新" class="headerlink" title="Updating(更新)"></a>Updating(更新)</h3><p>当组件的 props 或 state 发生变化时会触发更新。组件更新的生命周期调用顺序如下：</p><ul><li>getDerivedStateFromProps(): 在调用 render 方法之前调用，并且在初始挂载及后续更新时都会被调用。根据 shouldComponentUpdate() 的返回值，判断 React 组件的输出是否受当前 state 或 <code>props</code> 更改的影响。</li><li>shouldComponentUpdate():当 props 或 state 发生变化时，shouldComponentUpdate() 会在渲染执行之前被调用。</li><li>render(): render() 方法是 class 组件中唯一必须实现的方法。</li><li>getSnapshotBeforeUpdate(): 在最近一次渲染输出（提交到 DOM 节点）之前调用。</li><li>componentDidUpdate(): 在更新后会被立即调用。<br>render() 方法是 class 组件中唯一必须实现的方法，其他方法可以根据自己的需要来实现。</li></ul><h3 id="Unmounting-卸载"><a href="#Unmounting-卸载" class="headerlink" title="Unmounting(卸载)"></a>Unmounting(卸载)</h3><ul><li>componentDidUpdate(): 在更新后会被立即调用。</li></ul><p>声明周期实例:<br></p><figure class="highlight typescript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> &#123; <span class="title class_">Component</span> &#125; <span class="keyword">from</span> <span class="string">&#x27;react&#x27;</span>;</span><br><span class="line"><span class="keyword">import</span> <span class="title class_">ReactDOM</span> <span class="keyword">from</span> <span class="string">&#x27;react-dom/client&#x27;</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> <span class="keyword">class</span> <span class="title class_">Count</span> <span class="keyword">extends</span> <span class="title class_ inherited__">Component</span>&lt;<span class="built_in">any</span>, <span class="built_in">any</span>&gt;&#123;</span><br><span class="line">  <span class="comment">/* </span></span><br><span class="line"><span class="comment">    1. 初始化阶段: 由ReactDOM.render()触发---初次渲染</span></span><br><span class="line"><span class="comment">            1.	constructor()</span></span><br><span class="line"><span class="comment">            2.	getDerivedStateFromProps </span></span><br><span class="line"><span class="comment">            3.	render()</span></span><br><span class="line"><span class="comment">            4.	componentDidMount() =====&gt; 常用</span></span><br><span class="line"><span class="comment">                  一般在这个钩子中做一些初始化的事，例如：开启定时器、发送网络请求、订阅消息</span></span><br><span class="line"><span class="comment">    2. 更新阶段: 由组件内部this.setSate()或父组件重新render触发</span></span><br><span class="line"><span class="comment">            1.	getDerivedStateFromProps</span></span><br><span class="line"><span class="comment">            2.	shouldComponentUpdate()</span></span><br><span class="line"><span class="comment">            3.	render()</span></span><br><span class="line"><span class="comment">            4.	getSnapshotBeforeUpdate</span></span><br><span class="line"><span class="comment">            5.	componentDidUpdate()</span></span><br><span class="line"><span class="comment">    3. 卸载组件: 由ReactDOM.unmountComponentAtNode()触发</span></span><br><span class="line"><span class="comment">            1.	componentWillUnmount()  =====&gt; 常用</span></span><br><span class="line"><span class="comment">                  一般在这个钩子中做一些收尾的事，例如：关闭定时器、取消订阅消息</span></span><br><span class="line"><span class="comment">  */</span></span><br><span class="line">  <span class="comment">//构造器</span></span><br><span class="line">  <span class="title function_">constructor</span>(<span class="params">props: <span class="built_in">any</span></span>) &#123;</span><br><span class="line">    <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">&#x27;Count---constructor&#x27;</span>);</span><br><span class="line">    <span class="variable language_">super</span>(props)</span><br><span class="line">    <span class="comment">//初始化状态</span></span><br><span class="line">    <span class="variable language_">this</span>.<span class="property">state</span> = &#123; <span class="attr">count</span>: <span class="number">0</span> &#125;</span><br><span class="line">  &#125;</span><br><span class="line"></span><br><span class="line">  <span class="comment">//加1按钮的回调</span></span><br><span class="line">  add = <span class="function">() =&gt;</span> &#123;</span><br><span class="line">    <span class="comment">//获取原状态</span></span><br><span class="line">    <span class="keyword">const</span> &#123; count &#125; = <span class="variable language_">this</span>.<span class="property">state</span></span><br><span class="line">    <span class="comment">//更新状态</span></span><br><span class="line">    <span class="variable language_">this</span>.<span class="title function_">setState</span>(&#123; <span class="attr">count</span>: count + <span class="number">1</span> &#125;)</span><br><span class="line">  &#125;</span><br><span class="line"></span><br><span class="line">  <span class="comment">//卸载组件按钮的回调</span></span><br><span class="line">  death = <span class="function">() =&gt;</span> &#123;</span><br><span class="line">    <span class="keyword">const</span> root = <span class="title class_">ReactDOM</span>.<span class="title function_">createRoot</span>(</span><br><span class="line">      <span class="variable language_">document</span>.<span class="title function_">getElementById</span>(<span class="string">&#x27;test&#x27;</span>) <span class="keyword">as</span> <span class="title class_">HTMLElement</span></span><br><span class="line">    );</span><br><span class="line">    root.<span class="title function_">unmount</span>()</span><br><span class="line">  &#125;</span><br><span class="line"></span><br><span class="line">  <span class="comment">//强制更新按钮的回调</span></span><br><span class="line">  force = <span class="function">() =&gt;</span> &#123;</span><br><span class="line">    <span class="variable language_">this</span>.<span class="title function_">forceUpdate</span>()</span><br><span class="line">  &#125;</span><br><span class="line"></span><br><span class="line">  <span class="comment">//若state的值在任何时候都取决于props，那么可以使用getDerivedStateFromProps</span></span><br><span class="line">  <span class="keyword">static</span> <span class="title function_">getDerivedStateFromProps</span>(<span class="params">props: <span class="built_in">any</span>, state: <span class="built_in">any</span></span>) &#123;</span><br><span class="line">    <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">&#x27;getDerivedStateFromProps&#x27;</span>, props, state);</span><br><span class="line">    <span class="keyword">return</span> <span class="literal">null</span></span><br><span class="line">  &#125;</span><br><span class="line"></span><br><span class="line">  <span class="comment">//在更新之前获取快照</span></span><br><span class="line">  <span class="title function_">getSnapshotBeforeUpdate</span>(<span class="params"></span>) &#123;</span><br><span class="line">    <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">&#x27;getSnapshotBeforeUpdate&#x27;</span>);</span><br><span class="line">    <span class="keyword">return</span> <span class="string">&#x27;atguigu&#x27;</span></span><br><span class="line">  &#125;</span><br><span class="line"></span><br><span class="line">  <span class="comment">//组件挂载完毕的钩子</span></span><br><span class="line">  <span class="title function_">componentDidMount</span>(<span class="params"></span>) &#123;</span><br><span class="line">    <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">&#x27;Count---componentDidMount&#x27;</span>);</span><br><span class="line">  &#125;</span><br><span class="line"></span><br><span class="line">  <span class="comment">//组件将要卸载的钩子</span></span><br><span class="line">  <span class="title function_">componentWillUnmount</span>(<span class="params"></span>) &#123;</span><br><span class="line">    <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">&#x27;Count---componentWillUnmount&#x27;</span>);</span><br><span class="line">  &#125;</span><br><span class="line"></span><br><span class="line">  <span class="comment">//控制组件更新的“阀门”</span></span><br><span class="line">  <span class="title function_">shouldComponentUpdate</span>(<span class="params"></span>) &#123;</span><br><span class="line">    <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">&#x27;Count---shouldComponentUpdate&#x27;</span>);</span><br><span class="line">    <span class="keyword">return</span> <span class="literal">true</span></span><br><span class="line">  &#125;</span><br><span class="line"></span><br><span class="line">  <span class="comment">//组件更新完毕的钩子</span></span><br><span class="line">  <span class="title function_">componentDidUpdate</span>(<span class="params">preProps: <span class="built_in">any</span>, preState: <span class="built_in">any</span>, snapshotValue: <span class="built_in">any</span></span>) &#123;</span><br><span class="line">    <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">&#x27;Count---componentDidUpdate&#x27;</span>, preProps, preState, snapshotValue);</span><br><span class="line">  &#125;</span><br><span class="line"></span><br><span class="line">  <span class="title function_">render</span>(<span class="params"></span>) &#123;</span><br><span class="line">    <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">&#x27;Count---render&#x27;</span>);</span><br><span class="line">    <span class="keyword">const</span> &#123; count &#125; = <span class="variable language_">this</span>.<span class="property">state</span></span><br><span class="line">    <span class="keyword">return</span> (</span><br><span class="line">      <span class="language-xml"><span class="tag">&lt;<span class="name">div</span> <span class="attr">id</span>=<span class="string">&quot;test&quot;</span>&gt;</span></span></span><br><span class="line"><span class="language-xml">        <span class="tag">&lt;<span class="name">h2</span>&gt;</span>当前求和为：&#123;count&#125;<span class="tag">&lt;/<span class="name">h2</span>&gt;</span></span></span><br><span class="line"><span class="language-xml">        <span class="tag">&lt;<span class="name">button</span> <span class="attr">onClick</span>=<span class="string">&#123;this.add&#125;</span>&gt;</span>点我+1<span class="tag">&lt;/<span class="name">button</span>&gt;</span></span></span><br><span class="line"><span class="language-xml">        <span class="tag">&lt;<span class="name">button</span> <span class="attr">onClick</span>=<span class="string">&#123;this.death&#125;</span>&gt;</span>卸载组件<span class="tag">&lt;/<span class="name">button</span>&gt;</span></span></span><br><span class="line"><span class="language-xml">        <span class="tag">&lt;<span class="name">button</span> <span class="attr">onClick</span>=<span class="string">&#123;this.force&#125;</span>&gt;</span>不更改任何状态中的数据，强制更新一下<span class="tag">&lt;/<span class="name">button</span>&gt;</span></span></span><br><span class="line"><span class="language-xml">      <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span></span><br><span class="line">    )</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p></p><h2 id="Fragments"><a href="#Fragments" class="headerlink" title="Fragments"></a>Fragments</h2><p>React 中的一个常见模式是一个组件返回多个元素。Fragments 允许你将子列表分组，而无需向 DOM 添加额外节点。</p><figure class="highlight typescript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="title function_">render</span>(<span class="params"></span>) &#123;</span><br><span class="line">  <span class="keyword">return</span> (</span><br><span class="line">    <span class="language-xml"><span class="tag">&lt;<span class="name">React.Fragment</span>&gt;</span></span></span><br><span class="line"><span class="language-xml">      <span class="tag">&lt;<span class="name">ChildA</span> /&gt;</span></span></span><br><span class="line"><span class="language-xml">      <span class="tag">&lt;<span class="name">ChildB</span> /&gt;</span></span></span><br><span class="line"><span class="language-xml">      <span class="tag">&lt;<span class="name">ChildC</span> /&gt;</span></span></span><br><span class="line"><span class="language-xml">    <span class="tag">&lt;/<span class="name">React.Fragment</span>&gt;</span></span></span><br><span class="line">  );</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>短语法</p><figure class="highlight typescript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">class</span> <span class="title class_">Columns</span> <span class="keyword">extends</span> <span class="title class_ inherited__">React.Component</span> &#123;</span><br><span class="line">  <span class="title function_">render</span>(<span class="params"></span>) &#123;</span><br><span class="line">    <span class="keyword">return</span> (</span><br><span class="line">      <span class="language-xml"><span class="tag">&lt;&gt;</span></span></span><br><span class="line"><span class="language-xml">        <span class="tag">&lt;<span class="name">td</span>&gt;</span>Hello<span class="tag">&lt;/<span class="name">td</span>&gt;</span></span></span><br><span class="line"><span class="language-xml">        <span class="tag">&lt;<span class="name">td</span>&gt;</span>World<span class="tag">&lt;/<span class="name">td</span>&gt;</span></span></span><br><span class="line"><span class="language-xml">      <span class="tag">&lt;/&gt;</span></span></span><br><span class="line">    );</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h2 id="组件之间通信"><a href="#组件之间通信" class="headerlink" title="组件之间通信"></a>组件之间通信</h2><h3 id="⽗组件向⼦组件通讯"><a href="#⽗组件向⼦组件通讯" class="headerlink" title="⽗组件向⼦组件通讯"></a>⽗组件向⼦组件通讯</h3><div class="note flat info simple"><p>⽗组件可以通过向⼦组件传 props 的⽅式来实现父到子的通讯。</p></div><figure class="highlight typescript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> &#123; <span class="title class_">Component</span> &#125; <span class="keyword">from</span> <span class="string">&#x27;react&#x27;</span>;</span><br><span class="line"></span><br><span class="line">  <span class="keyword">class</span> <span class="title class_">Parent</span> <span class="keyword">extends</span> <span class="title class_ inherited__">Component</span>&lt;<span class="built_in">any</span>,<span class="built_in">any</span>&gt; &#123;</span><br><span class="line">    state = &#123;<span class="attr">name</span>:<span class="string">&#x27;我是子组件&#x27;</span>&#125;</span><br><span class="line">    <span class="title function_">render</span>(<span class="params"></span>) &#123;</span><br><span class="line">      <span class="keyword">const</span> &#123; name &#125; = <span class="variable language_">this</span>.<span class="property">state</span></span><br><span class="line">      <span class="keyword">return</span> (</span><br><span class="line">        <span class="language-xml"><span class="tag">&lt;<span class="name">div</span>&gt;</span></span></span><br><span class="line"><span class="language-xml">          <span class="tag">&lt;<span class="name">h1</span>&gt;</span>Holle React!<span class="tag">&lt;/<span class="name">h1</span>&gt;</span></span></span><br><span class="line"><span class="language-xml">          // 父组件通过 props 向子组件传递数据</span></span><br><span class="line"><span class="language-xml">          <span class="tag">&lt;<span class="name">Child</span> <span class="attr">name</span>=<span class="string">&#123;name&#125;</span> /&gt;</span></span></span><br><span class="line"><span class="language-xml">        <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span></span><br><span class="line">      )</span><br><span class="line">    &#125;</span><br><span class="line">  &#125;</span><br><span class="line"></span><br><span class="line">  <span class="keyword">class</span> <span class="title class_">Child</span> <span class="keyword">extends</span> <span class="title class_ inherited__">Component</span>&lt;<span class="built_in">any</span>,<span class="built_in">any</span>&gt; &#123;</span><br><span class="line">    <span class="title function_">render</span>(<span class="params"></span>) &#123;</span><br><span class="line">      <span class="comment">// 子组件接收数据</span></span><br><span class="line">      <span class="keyword">const</span> &#123; name &#125; = <span class="variable language_">this</span>.<span class="property">props</span></span><br><span class="line">      <span class="keyword">return</span> <span class="language-xml"><span class="tag">&lt;<span class="name">h1</span>&gt;</span>Holle &#123;name&#125;!<span class="tag">&lt;/<span class="name">h1</span>&gt;</span></span></span><br><span class="line">    &#125;</span><br><span class="line">  &#125;</span><br></pre></td></tr></table></figure><h3 id="⼦组件向⽗组件通讯"><a href="#⼦组件向⽗组件通讯" class="headerlink" title="⼦组件向⽗组件通讯"></a>⼦组件向⽗组件通讯</h3><div class="note flat info simple"><p>当⽗组件向⼦组件传递 props 进⾏通讯时，可在该 props 中传递一个回调函数，当⼦组件调⽤该函数时，可将⼦组件中想要传递给父组件的信息作为参数传递给该函数。由于 props 中的函数作⽤域为⽗组件⾃身，因此可以通过该函数内的 setState 更新到⽗组件上。</p></div><figure class="highlight typescript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> &#123; <span class="title class_">Component</span> &#125; <span class="keyword">from</span> <span class="string">&#x27;react&#x27;</span>;</span><br><span class="line"></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">Parent</span> <span class="keyword">extends</span> <span class="title class_ inherited__">Component</span>&lt;<span class="built_in">any</span>, <span class="built_in">any</span>&gt; &#123;</span><br><span class="line">  receiveData = <span class="function">(<span class="params">data: <span class="built_in">string</span></span>) =&gt;</span> &#123;</span><br><span class="line">    <span class="comment">// 子组件向父组件传递的数据</span></span><br><span class="line">    <span class="variable language_">console</span>.<span class="title function_">log</span>(data)</span><br><span class="line">  &#125;</span><br><span class="line">  <span class="title function_">render</span>(<span class="params"></span>) &#123;</span><br><span class="line">    <span class="keyword">return</span> (</span><br><span class="line">      <span class="language-xml"><span class="tag">&lt;<span class="name">div</span>&gt;</span></span></span><br><span class="line"><span class="language-xml">        <span class="tag">&lt;<span class="name">h1</span>&gt;</span>Holle React!<span class="tag">&lt;/<span class="name">h1</span>&gt;</span></span></span><br><span class="line"><span class="language-xml">          // 父组件通过 props 向子组件传递数据</span></span><br><span class="line"><span class="language-xml">        <span class="tag">&lt;<span class="name">Child</span> <span class="attr">receiveData</span>=<span class="string">&#123;this.receiveData&#125;</span> /&gt;</span></span></span><br><span class="line"><span class="language-xml">      <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span></span><br><span class="line">    )</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">Child</span> <span class="keyword">extends</span> <span class="title class_ inherited__">Component</span>&lt;<span class="built_in">any</span>, <span class="built_in">any</span>&gt; &#123;</span><br><span class="line">  <span class="title function_">componentDidMount</span>(<span class="params"></span>) &#123;</span><br><span class="line">    <span class="keyword">const</span> msg = <span class="string">&#x27;子组件向父组件传递的数据&#x27;</span></span><br><span class="line">    <span class="variable language_">this</span>.<span class="property">props</span>.<span class="title function_">receiveData</span>(msg)</span><br><span class="line">  &#125;</span><br><span class="line">  <span class="title function_">render</span>(<span class="params"></span>) &#123;</span><br><span class="line">    <span class="keyword">return</span> <span class="language-xml"><span class="tag">&lt;<span class="name">h1</span>&gt;</span>Holle React!<span class="tag">&lt;/<span class="name">h1</span>&gt;</span></span></span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="兄弟组件中通信"><a href="#兄弟组件中通信" class="headerlink" title="兄弟组件中通信"></a>兄弟组件中通信</h3><div class="note flat info simple"><ol><li>可以利用父子组件中的 props，例如 A 是父组件，B 和 C 都是 A 种的子组件且是兄弟组件，B 可以通过 props 回调传递给 A，然后A再通过 props传递给 C。</li><li>可以考虑下面的通信方式 events 自定义事件通信 和 消息订阅与发布机制</li></ol></div><h3 id="events-自定义事件通信"><a href="#events-自定义事件通信" class="headerlink" title="events 自定义事件通信"></a>events 自定义事件通信</h3><ol><li>安装 events<figure class="highlight powershell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">yarn add events</span><br><span class="line">npm i events</span><br></pre></td></tr></table></figure></li><li>创建一个 events.js 文件，在该文件中生成事件总线：<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> &#123; <span class="title class_">EventEmitter</span> &#125; <span class="keyword">from</span> <span class="string">&#x27;events&#x27;</span>;</span><br><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> <span class="keyword">new</span> <span class="title class_">EventEmitter</span>();</span><br></pre></td></tr></table></figure></li><li>在负责接收数据的组件中，给事件总线身上添加事件：<figure class="highlight typescript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> &#123; <span class="title class_">Component</span> &#125; <span class="keyword">from</span> <span class="string">&#x27;react&#x27;</span></span><br><span class="line"><span class="keyword">import</span> emitter <span class="keyword">from</span> <span class="string">&#x27;./utils/event&#x27;</span></span><br><span class="line"><span class="keyword">import</span> <span class="title class_">Child</span> <span class="keyword">from</span> <span class="string">&#x27;./Child&#x27;</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> <span class="keyword">class</span> <span class="title class_">App</span> <span class="keyword">extends</span> <span class="title class_ inherited__">Component</span> &#123;</span><br><span class="line">  state = &#123; <span class="attr">message</span>: <span class="string">&#x27;&#x27;</span> &#125;</span><br><span class="line">  <span class="attr">eventEmitter</span>: <span class="built_in">any</span> = <span class="literal">null</span></span><br><span class="line">  getData = <span class="function">(<span class="params">message: <span class="built_in">string</span></span>) =&gt;</span> &#123;</span><br><span class="line">    <span class="variable language_">this</span>.<span class="title function_">setState</span>(&#123;</span><br><span class="line">      message,</span><br><span class="line">    &#125;);</span><br><span class="line">  &#125;</span><br><span class="line">  <span class="comment">// 组件挂载完成</span></span><br><span class="line">  <span class="title function_">componentDidMount</span>(<span class="params"></span>) &#123;</span><br><span class="line">    <span class="comment">// 组件装载完成以后声明一个自定义事件</span></span><br><span class="line">    <span class="variable language_">this</span>.<span class="property">eventEmitter</span> = emitter.<span class="title function_">addListener</span>(<span class="string">&#x27;childMsg&#x27;</span>, <span class="variable language_">this</span>.<span class="property">getData</span>);</span><br><span class="line">  &#125;</span><br><span class="line">  <span class="comment">// 记得在 componentWillUnmount 钩子中移除 addListener</span></span><br><span class="line">  <span class="title function_">componentWillUnmount</span>(<span class="params"></span>) &#123;</span><br><span class="line">    emitter.<span class="title function_">removeListener</span>(<span class="string">&#x27;childMsg&#x27;</span>, <span class="variable language_">this</span>.<span class="property">getData</span>);</span><br><span class="line">  &#125;</span><br><span class="line">  <span class="title function_">render</span>(<span class="params"></span>) &#123;</span><br><span class="line">    <span class="keyword">return</span> (</span><br><span class="line">      <span class="language-xml"><span class="tag">&lt;<span class="name">div</span>&gt;</span></span></span><br><span class="line"><span class="language-xml">        <span class="tag">&lt;<span class="name">h1</span>&gt;</span>子组件B：负责接收数据<span class="tag">&lt;/<span class="name">h1</span>&gt;</span></span></span><br><span class="line"><span class="language-xml">        <span class="tag">&lt;<span class="name">p</span>&gt;</span>接收到的数据：&#123;this.state.message&#125;<span class="tag">&lt;/<span class="name">p</span>&gt;</span></span></span><br><span class="line"><span class="language-xml">        <span class="tag">&lt;<span class="name">Child</span> /&gt;</span></span></span><br><span class="line"><span class="language-xml">      <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span></span><br><span class="line">    )</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><pre><code>4. 在负责传递数据的组件中，去调用事件总线身上的事件：
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> emitter <span class="keyword">from</span> <span class="string">&#x27;./utils/event&#x27;</span></span><br><span class="line"><span class="keyword">import</span> &#123; <span class="title class_">Component</span> &#125; <span class="keyword">from</span> <span class="string">&#x27;react&#x27;</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> <span class="keyword">class</span> <span class="title class_">ChildA</span> <span class="keyword">extends</span> <span class="title class_ inherited__">Component</span> &#123;</span><br><span class="line">    state = &#123;</span><br><span class="line">        <span class="attr">message</span>: <span class="string">&#x27;张三&#x27;</span></span><br><span class="line">    &#125;</span><br><span class="line">    sendData = <span class="function">() =&gt;</span> &#123;</span><br><span class="line">        emitter.<span class="title function_">emit</span>(<span class="string">&#x27;childMsg&#x27;</span>, <span class="variable language_">this</span>.<span class="property">state</span>.<span class="property">message</span>)</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="title function_">render</span>(<span class="params"></span>) &#123;</span><br><span class="line">        <span class="keyword">return</span> (</span><br><span class="line">            <span class="language-xml"><span class="tag">&lt;<span class="name">div</span>&gt;</span></span></span><br><span class="line"><span class="language-xml">                <span class="tag">&lt;<span class="name">h1</span>&gt;</span>子组件A：负责传递数据<span class="tag">&lt;/<span class="name">h1</span>&gt;</span></span></span><br><span class="line"><span class="language-xml">                <span class="tag">&lt;<span class="name">button</span> <span class="attr">onClick</span>=<span class="string">&#123;this.sendData&#125;</span>&gt;</span>按钮<span class="tag">&lt;/<span class="name">button</span>&gt;</span></span></span><br><span class="line"><span class="language-xml">            <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span></span><br><span class="line">        )</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></code></pre><img src="" data-lazy-src="https://s2.loli.net/2022/07/05/37LVrG1ztJuEhqk.jpg" alt="1657013477233.jpg"></li></ol><h3 id="消息订阅与发布机制"><a href="#消息订阅与发布机制" class="headerlink" title="消息订阅与发布机制"></a>消息订阅与发布机制</h3><ol><li>安装 pubsub-js<figure class="highlight powershell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">yarn add pubsub<span class="literal">-js</span></span><br><span class="line">npm i pubsub<span class="literal">-js</span></span><br></pre></td></tr></table></figure></li><li>在组件中发布消息<figure class="highlight typescript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> <span class="title class_">PubSub</span> <span class="keyword">from</span> <span class="string">&#x27;pubsub-js&#x27;</span></span><br><span class="line"><span class="keyword">import</span> &#123; <span class="title class_">Component</span> &#125; <span class="keyword">from</span> <span class="string">&#x27;react&#x27;</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> <span class="keyword">class</span> <span class="title class_">ChildA</span> <span class="keyword">extends</span> <span class="title class_ inherited__">Component</span> &#123;</span><br><span class="line">    state = &#123;</span><br><span class="line">        <span class="attr">message</span>: <span class="string">&#x27;张三&#x27;</span></span><br><span class="line">    &#125;</span><br><span class="line">    sendData = <span class="function">() =&gt;</span> &#123;</span><br><span class="line">        <span class="comment">// 发布消息</span></span><br><span class="line">        <span class="title class_">PubSub</span>.<span class="title function_">publish</span>(<span class="string">&#x27;childMsg&#x27;</span>, <span class="variable language_">this</span>.<span class="property">state</span>.<span class="property">message</span>)</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="title function_">render</span>(<span class="params"></span>) &#123;</span><br><span class="line">        <span class="keyword">return</span> (</span><br><span class="line">            <span class="language-xml"><span class="tag">&lt;<span class="name">div</span>&gt;</span></span></span><br><span class="line"><span class="language-xml">                <span class="tag">&lt;<span class="name">h1</span>&gt;</span>子组件A：负责传递数据<span class="tag">&lt;/<span class="name">h1</span>&gt;</span></span></span><br><span class="line"><span class="language-xml">                <span class="tag">&lt;<span class="name">button</span> <span class="attr">onClick</span>=<span class="string">&#123;this.sendData&#125;</span>&gt;</span>按钮<span class="tag">&lt;/<span class="name">button</span>&gt;</span></span></span><br><span class="line"><span class="language-xml">            <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span></span><br><span class="line">        )</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></li><li>组件中订阅消息<figure class="highlight typescript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> &#123; <span class="variable constant_">FC</span>, useState, useEffect &#125; <span class="keyword">from</span> <span class="string">&#x27;react&#x27;</span></span><br><span class="line"><span class="keyword">import</span> <span class="title class_">PubSub</span> <span class="keyword">from</span> <span class="string">&#x27;pubsub-js&#x27;</span></span><br><span class="line"><span class="keyword">import</span> <span class="title class_">Child</span> <span class="keyword">from</span> <span class="string">&#x27;./Child&#x27;</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> <span class="title class_">App</span>: <span class="variable constant_">FC</span> = <span class="function">() =&gt;</span> &#123;</span><br><span class="line">  <span class="keyword">const</span> [msg, setMsg] = <span class="title function_">useState</span>(<span class="string">&#x27;&#x27;</span>)</span><br><span class="line">  <span class="keyword">let</span> <span class="title class_">PubSubEmitter</span>: <span class="built_in">any</span> = <span class="literal">null</span></span><br><span class="line">  <span class="title function_">useEffect</span>(<span class="function">() =&gt;</span> &#123;</span><br><span class="line">    <span class="comment">// 订阅消息</span></span><br><span class="line">    <span class="title class_">PubSubEmitter</span> = <span class="title class_">PubSub</span>.<span class="title function_">subscribe</span>(<span class="string">&#x27;childMsg&#x27;</span>, <span class="function">(<span class="params">msg, data</span>) =&gt;</span> &#123;</span><br><span class="line">      <span class="title function_">setMsg</span>(data)</span><br><span class="line">    &#125;)</span><br><span class="line">    <span class="comment">// 组件卸载前取消消息订阅</span></span><br><span class="line">    <span class="keyword">return</span> <span class="function">() =&gt;</span> &#123;</span><br><span class="line">      <span class="title class_">PubSub</span>.<span class="title function_">unsubscribe</span>(<span class="title class_">PubSubEmitter</span>)</span><br><span class="line">    &#125;</span><br><span class="line">  &#125;, [])</span><br><span class="line">  <span class="keyword">return</span> (</span><br><span class="line">    <span class="language-xml"><span class="tag">&lt;<span class="name">div</span>&gt;</span></span></span><br><span class="line"><span class="language-xml">      <span class="tag">&lt;<span class="name">h1</span>&gt;</span>子组件B：负责接收数据<span class="tag">&lt;/<span class="name">h1</span>&gt;</span></span></span><br><span class="line"><span class="language-xml">      <span class="tag">&lt;<span class="name">p</span>&gt;</span>接收到的数据：&#123;msg&#125;<span class="tag">&lt;/<span class="name">p</span>&gt;</span></span></span><br><span class="line"><span class="language-xml">      <span class="tag">&lt;<span class="name">Child</span> /&gt;</span></span></span><br><span class="line"><span class="language-xml">    <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span></span><br><span class="line">  )</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> <span class="title class_">App</span></span><br></pre></td></tr></table></figure><img src="" data-lazy-src="https://s2.loli.net/2022/07/05/37LVrG1ztJuEhqk.jpg" alt="1657013477233.jpg"></li></ol><h2 id="HOOK"><a href="#HOOK" class="headerlink" title="HOOK"></a>HOOK</h2><h3 id="什么是-Hook"><a href="#什么是-Hook" class="headerlink" title="什么是 Hook?"></a>什么是 Hook?</h3><div class="note flat info simple"><p>Hook 是一些可以让你在函数组件里“钩入” React state 及生命周期等特性的函数。Hook 不能在 class 组件中使用 —— 这使得你不使用 class 也能使用 React。</p></div><h3 id="State-Hook"><a href="#State-Hook" class="headerlink" title="State Hook"></a>State Hook</h3><div class="note flat info simple"><p>在 useState()中，它接受状态的初始值作为参数，即上例中计数的初始值，它返回一个数组，其中数组第一项为一个变量，指向状态的当前值。类似 this.state,第二项是一个函数，用来更新状态,类似 setState。</p></div><figure class="highlight typescript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> &#123; useState,<span class="variable constant_">FC</span> &#125; <span class="keyword">from</span> <span class="string">&#x27;react&#x27;</span>;</span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> <span class="title class_">App</span>: <span class="variable constant_">FC</span> = <span class="function">()=&gt;</span> &#123;</span><br><span class="line">  <span class="comment">// 声明一个叫 &quot;count&quot; 的 state 变量</span></span><br><span class="line">  <span class="keyword">const</span> [count, setCount] = <span class="title function_">useState</span>(<span class="number">0</span>);</span><br><span class="line"></span><br><span class="line">  <span class="keyword">return</span> (</span><br><span class="line">    <span class="language-xml"><span class="tag">&lt;<span class="name">div</span>&gt;</span></span></span><br><span class="line"><span class="language-xml">      <span class="tag">&lt;<span class="name">p</span>&gt;</span>You clicked &#123;count&#125; times<span class="tag">&lt;/<span class="name">p</span>&gt;</span></span></span><br><span class="line"><span class="language-xml">      <span class="tag">&lt;<span class="name">button</span> <span class="attr">onClick</span>=<span class="string">&#123;()</span> =&gt;</span> setCount(count + 1)&#125;&gt;Click me<span class="tag">&lt;/<span class="name">button</span>&gt;</span></span></span><br><span class="line"><span class="language-xml">    <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span></span><br><span class="line">  );</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> <span class="title class_">App</span></span><br></pre></td></tr></table></figure><h3 id="Effect-Hook"><a href="#Effect-Hook" class="headerlink" title="Effect Hook"></a>Effect Hook</h3><div class="note flat info simple"><p>它可以用来更好的处理副作用，如异步请求等；可以把 useEffect Hook 看做 componentDidMount，componentDidUpdate 和 componentWillUnmount 这三个函数的组合。</p></div><figure class="highlight typescript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> &#123; useState, useEffect, <span class="variable constant_">FC</span> &#125; <span class="keyword">from</span> <span class="string">&#x27;react&#x27;</span>;</span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> <span class="title class_">App</span>: <span class="variable constant_">FC</span> = <span class="function">() =&gt;</span> &#123;</span><br><span class="line">  <span class="comment">// 声明一个叫 &quot;count&quot; 的 state 变量</span></span><br><span class="line">  <span class="keyword">const</span> [count, setCount] = <span class="title function_">useState</span>(<span class="number">0</span>);</span><br><span class="line">  <span class="comment">// 更改网页标题</span></span><br><span class="line">  <span class="title function_">useEffect</span>(<span class="function">() =&gt;</span> &#123;</span><br><span class="line">    <span class="variable language_">document</span>.<span class="property">title</span> = <span class="string">`You clicked <span class="subst">$&#123;count&#125;</span> times`</span>;</span><br><span class="line">  &#125;, [count])</span><br><span class="line">  <span class="keyword">return</span> (</span><br><span class="line">    <span class="language-xml"><span class="tag">&lt;<span class="name">div</span>&gt;</span></span></span><br><span class="line"><span class="language-xml">      <span class="tag">&lt;<span class="name">p</span>&gt;</span>You clicked &#123;count&#125; times<span class="tag">&lt;/<span class="name">p</span>&gt;</span></span></span><br><span class="line"><span class="language-xml">      <span class="tag">&lt;<span class="name">button</span> <span class="attr">onClick</span>=<span class="string">&#123;()</span> =&gt;</span> setCount(count + 1)&#125;&gt;Click me<span class="tag">&lt;/<span class="name">button</span>&gt;</span></span></span><br><span class="line"><span class="language-xml">    <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span></span><br><span class="line">  );</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> <span class="title class_">App</span></span><br></pre></td></tr></table></figure><blockquote><p>使用useEffect模拟react三个生命周期</p></blockquote><ol><li>实现 componentDidMount<figure class="highlight typescript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> &#123; useState, useEffect, <span class="variable constant_">FC</span> &#125; <span class="keyword">from</span> <span class="string">&#x27;react&#x27;</span>;</span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> <span class="title class_">App</span>: <span class="variable constant_">FC</span> = <span class="function">() =&gt;</span>  &#123;</span><br><span class="line">  <span class="keyword">const</span> [count, setCount] = <span class="title function_">useState</span>(<span class="number">0</span>);</span><br><span class="line">  <span class="title function_">useEffect</span>(<span class="function">() =&gt;</span> &#123;</span><br><span class="line">    <span class="title function_">getList</span>() <span class="comment">// 调用方法发起异步请求</span></span><br><span class="line">  &#125;, [])；</span><br><span class="line">  </span><br><span class="line"> <span class="keyword">return</span> (</span><br><span class="line">      <span class="language-xml"><span class="tag">&lt;<span class="name">div</span>&gt;</span></span></span><br><span class="line"><span class="language-xml">            hello world</span></span><br><span class="line"><span class="language-xml">      <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span></span><br><span class="line">  )</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></li><li>实现 componentDidUpdate<figure class="highlight typescript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> &#123; useState, useEffect, <span class="variable constant_">FC</span> &#125; <span class="keyword">from</span> <span class="string">&#x27;react&#x27;</span>;</span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> <span class="title class_">App</span>: <span class="variable constant_">FC</span> = <span class="function">() =&gt;</span>  &#123;</span><br><span class="line">  <span class="keyword">const</span> [count, setCount] = <span class="title function_">useState</span>(<span class="number">0</span>);</span><br><span class="line">  <span class="title function_">useEffect</span>(<span class="function">() =&gt;</span> &#123;</span><br><span class="line">    <span class="title function_">getList</span>() <span class="comment">// 仅在count更改时更新</span></span><br><span class="line">  &#125;, [count])；</span><br><span class="line">  </span><br><span class="line"> <span class="keyword">return</span> (</span><br><span class="line">      <span class="language-xml"><span class="tag">&lt;<span class="name">div</span>&gt;</span></span></span><br><span class="line"><span class="language-xml">            hello world</span></span><br><span class="line"><span class="language-xml">      <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span></span><br><span class="line">  )</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></li><li>实现 componentWillUnmount<figure class="highlight typescript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> &#123; useState, useEffect, <span class="variable constant_">FC</span> &#125; <span class="keyword">from</span> <span class="string">&#x27;react&#x27;</span>;</span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> <span class="title class_">App</span>: <span class="variable constant_">FC</span> = <span class="function">() =&gt;</span>  &#123;</span><br><span class="line">  <span class="title function_">useEffect</span>(<span class="function">() =&gt;</span> &#123;</span><br><span class="line">    <span class="title function_">getList</span>();</span><br><span class="line">    <span class="keyword">return</span> <span class="function">() =&gt;</span> &#123;</span><br><span class="line">        <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">&#x27;组件注销, 实现componentWillUnmount&#x27;</span>);</span><br><span class="line">    &#125;;</span><br><span class="line">  &#125;, [])；</span><br><span class="line">  </span><br><span class="line"> <span class="keyword">return</span> (</span><br><span class="line">      <span class="language-xml"><span class="tag">&lt;<span class="name">div</span>&gt;</span></span></span><br><span class="line"><span class="language-xml">            hello world</span></span><br><span class="line"><span class="language-xml">      <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span></span><br><span class="line">  )</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><div class="note flat warning simple"><p>useEffect的第二个参数集中形式:</p><ol><li>不传: useEffect 会在第一次渲染以及每次更新渲染后都执行。(不建议)</li><li>空数组: useEffect 会在第一次渲染后执行一次。</li><li>由基本类型或者引用类型组成的数组: useEffect 会在第一次渲染以及每次更新渲染后都执行。</li></ol></div></li></ol><h1 id="Todo"><a href="#Todo" class="headerlink" title="Todo"></a>Todo</h1><div class="checkbox blue checked"><input type="checkbox" checked><p><a href="/post/519afa7c.html">Vue3 中如何使用 JSX 语法</a></p></div></article><div class="post-copyright"><div class="post-copyright__author"><span class="post-copyright-meta">文章作者:</span> <span class="post-copyright-info"><a href="https://xmwpro.com">Cyan</a></span></div><div class="post-copyright__type"><span class="post-copyright-meta">文章链接:</span> <span class="post-copyright-info"><a href="https://xmwpro.com/post/2b445cd9.html">https://xmwpro.com/post/2b445cd9.html</a></span></div><div class="post-copyright__notice"><span class="post-copyright-meta">版权声明:</span> <span class="post-copyright-info">本博客所有文章除特别声明外，均采用 <a href="https://creativecommons.org/licenses/by-nc-sa/4.0/" rel="external nofollow noreferrer" target="_blank">CC BY-NC-SA 4.0</a> 许可协议。转载请注明来自 <a href="https://xmwpro.com" target="_blank">Cyan</a>！</span></div></div><div class="tag_share"><div class="post-meta__tag-list"><a class="post-meta__tags" href="/tags/React/"><span class="tags-punctuation">#</span><span class="tags-name">React</span><sup>7</sup></a></div><div class="post_share"><div class="social-share" data-image="https://ali-oss.xmwpro.com/global/avatar.jpg" data-sites="facebook,twitter,wechat,weibo,qq"></div><link rel="stylesheet" href="https://ali-oss.xmwpro.com/cdn/css/share.min.css" media="print" onload='this.media="all"'><script src="https://ali-oss.xmwpro.com/cdn/js/social-share.min.js" defer></script></div></div><div class="post-reward"><div class="reward-button"><i class="fas fa-qrcode"></i> 打赏</div><div class="reward-main"><ul class="reward-all"><li class="reward-item"><a href="https://ali-oss.xmwpro.com/global/wx-pay.jpeg" rel="external nofollow noreferrer" target="_blank"><img class="post-qr-code-img" src="" data-lazy-src="https://ali-oss.xmwpro.com/global/wx-pay.jpeg" alt="微信"></a><div class="post-qr-code-desc">微信</div></li><li class="reward-item"><a href="https://ali-oss.xmwpro.com/global/zfb-pay.jpeg" rel="external nofollow noreferrer" target="_blank"><img class="post-qr-code-img" src="" data-lazy-src="https://ali-oss.xmwpro.com/global/zfb-pay.jpeg" alt="支付宝"></a><div class="post-qr-code-desc">支付宝</div></li></ul></div></div><nav class="pagination-post" id="pagination"><div class="prev-post pull-left"><a href="/post/519afa7c.html" title="Vue3 中如何使用 JSX 语法"><img class="cover" src="" data-lazy-src="https://ali-oss.xmwpro.com/posts/post_cover25.jpg" onerror='onerror=null,src="/img/404.jpg"' alt="cover of previous post"><div class="pagination-info"><div class="label">上一篇</div><div class="prev_info">Vue3 中如何使用 JSX 语法</div></div></a></div><div class="next-post pull-right"><a href="/post/13d20048.html" title="create-react-app 配置路径别名"><img class="cover" src="" data-lazy-src="https://ali-oss.xmwpro.com/posts/post_cover43.jpg" onerror='onerror=null,src="/img/404.jpg"' alt="cover of next post"><div class="pagination-info"><div class="label">下一篇</div><div class="next_info">create-react-app 配置路径别名</div></div></a></div></nav><div class="relatedPosts"><div class="headline"><i class="fas fa-thumbs-up fa-fw"></i><span>相关推荐</span></div><div class="relatedPosts-list swiper"><div class="swiper-wrapper"><div class="swiper-slide related-item"><a href="/post/d3bfdf4d.html" title="create-react-app 配置代理"><img class="cover" src="" data-lazy-src="https://ali-oss.xmwpro.com/posts/post_cover48.jpg" alt="cover"><div class="content is-center"><div class="date"><i class="far fa-calendar-alt fa-fw"></i> 2022-07-07</div><div class="title">create-react-app 配置代理</div></div></a></div><div class="swiper-slide related-item"><a href="/post/13d20048.html" title="create-react-app 配置路径别名"><img class="cover" src="" data-lazy-src="https://ali-oss.xmwpro.com/posts/post_cover25.jpg" alt="cover"><div class="content is-center"><div class="date"><i class="far fa-calendar-alt fa-fw"></i> 2022-07-07</div><div class="title">create-react-app 配置路径别名</div></div></a></div><div class="swiper-slide related-item"><a href="/post/e140163a.html" title="React - 实现一个基于 Antd 的密码强度校验组件"><img class="cover" src="" data-lazy-src="https://ali-oss.xmwpro.com/posts/post_cover7.jpg" alt="cover"><div class="content is-center"><div class="date"><i class="far fa-calendar-alt fa-fw"></i> 2023-01-16</div><div class="title">React - 实现一个基于 Antd 的密码强度校验组件</div></div></a></div><div class="swiper-slide related-item"><a href="/post/e89dda9d.html" title="React - 实现一个基于 Antd 的下拉懒加载组件"><img class="cover" src="" data-lazy-src="https://ali-oss.xmwpro.com/posts/post_cover27.jpg" alt="cover"><div class="content is-center"><div class="date"><i class="far fa-calendar-alt fa-fw"></i> 2023-03-10</div><div class="title">React - 实现一个基于 Antd 的下拉懒加载组件</div></div></a></div><div class="swiper-slide related-item"><a href="/post/7b74bd27.html" title="基于 React + Nest 的后台应用"><img class="cover" src="" data-lazy-src="https://ali-oss.xmwpro.com/posts/post_cover9.jpg" alt="cover"><div class="content is-center"><div class="date"><i class="far fa-calendar-alt fa-fw"></i> 2023-04-18</div><div class="title">基于 React + Nest 的后台应用</div></div></a></div><div class="swiper-slide related-item"><a href="/post/1ce87d42.html" title="使用 sort-imports 排序规则美化头部 import 代码"><img class="cover" src="" data-lazy-src="https://ali-oss.xmwpro.com/posts/post_cover49.jpg" alt="cover"><div class="content is-center"><div class="date"><i class="far fa-calendar-alt fa-fw"></i> 2023-06-06</div><div class="title">使用 sort-imports 排序规则美化头部 import 代码</div></div></a></div></div><div class="related-swiper-scrollbar"></div></div></div><div id="post-comment"><div class="comment-head"><div class="comment-headline"><i class="fas fa-comments fa-fw"></i> <span>评论</span></div><div class="comment-tips">您无需删除空行，直接评论以获取最佳展示效果</div></div><div class="comment-wrap"><div><div id="twikoo-wrap"></div></div></div><div class="barrageswiper"><div class="swiper"><div class="swiper-wrapper"></div></div></div></div></div><div class="aside-content" id="aside-content"><div class="card-widget card-info"><div class="card-info-my"><div class="card-info-my-avatar"><img src="" data-lazy-src="https://ali-oss.xmwpro.com/global/avatar.jpg" onerror='this.onerror=null,this.src="/img/friend_404.gif"' alt="avatar"></div><div class="card-info-my-name"><div class="card-info-my-name-welcome"></div><div class="card-info-my-name-text">谢明伟</div></div></div><div class="card-info-content"><b>记录学习、生活和有趣的事</b></div><div class="card-info-announcement">好好吃饭🍣 好好睡觉💤 敲敲代码💻 谈谈恋爱💑</div><div class="card-info-social"><div class="card-info-social-icon"><a class="social-icon" href="https://github.com/Cyan-Xmw" rel="external nofollow noreferrer" target="_blank" title="Github"><i class="iconfont cyan-github-fill"></i></a></div><a class="card-info-social-more" href="/about/"><i class="fas fa-circle-chevron-right"></i><span class="card-info-social-more-text">了解更多</span></a></div></div><div class="sticky_layout"><div class="card-widget" id="card-toc"><div class="toc-content"><ol class="toc"><li class="toc-item toc-level-2"><a class="toc-link" href="#%E4%BB%80%E4%B9%88%E6%98%AF-React"><span class="toc-number">1.</span> <span class="toc-text">什么是 React</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#React-%E5%92%8C-Vue-%E7%9A%84%E5%8C%BA%E5%88%AB"><span class="toc-number">2.</span> <span class="toc-text">React 和 Vue 的区别</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#%E6%A0%B8%E5%BF%83%E6%80%9D%E6%83%B3%E4%B8%8D%E5%90%8C"><span class="toc-number">2.1.</span> <span class="toc-text">核心思想不同</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#%E5%A3%B0%E6%98%8E%E5%BC%8F%E6%98%AF%E4%BB%80%E4%B9%88%E6%84%8F%E6%80%9D%EF%BC%9F"><span class="toc-number">2.1.1.</span> <span class="toc-text">声明式是什么意思？</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#%E7%BB%84%E4%BB%B6%E5%8C%96%E6%98%AF%E4%BB%80%E4%B9%88%E6%84%8F%E6%80%9D%EF%BC%9F"><span class="toc-number">2.1.2.</span> <span class="toc-text">组件化是什么意思？</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#%E5%A6%82%E4%BD%95%E7%90%86%E8%A7%A3React%E7%9A%84%E5%8D%95%E5%90%91%E6%95%B0%E6%8D%AE%E6%B5%81%EF%BC%9F"><span class="toc-number">2.1.3.</span> <span class="toc-text">如何理解React的单向数据流？</span></a></li></ol></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E7%BB%84%E4%BB%B6%E5%86%99%E6%B3%95%E4%B8%8A%E4%B8%8D%E5%90%8C"><span class="toc-number">2.2.</span> <span class="toc-text">组件写法上不同</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#diff-%E7%AE%97%E6%B3%95%E4%B8%8D%E5%90%8C"><span class="toc-number">2.3.</span> <span class="toc-text">diff 算法不同</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E5%93%8D%E5%BA%94%E5%BC%8F%E5%8E%9F%E7%90%86%E4%B8%8D%E5%90%8C"><span class="toc-number">2.4.</span> <span class="toc-text">响应式原理不同</span></a></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E4%BB%80%E4%B9%88%E6%98%AF-JSX-%EF%BC%9F"><span class="toc-number">3.</span> <span class="toc-text">什么是 JSX ？</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E5%87%BD%E6%95%B0%E5%BC%8F%E7%BB%84%E4%BB%B6%E5%92%8C%E7%B1%BB%E7%BB%84%E4%BB%B6"><span class="toc-number">4.</span> <span class="toc-text">函数式组件和类组件</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#%E4%BB%80%E4%B9%88%E6%98%AF%E5%87%BD%E6%95%B0%E5%BC%8F%E7%BB%84%E4%BB%B6-%E6%97%A0%E7%8A%B6%E6%80%81"><span class="toc-number">4.1.</span> <span class="toc-text">什么是函数式组件(无状态)</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E4%BB%80%E4%B9%88%E6%98%AF%E7%B1%BB%E7%BB%84%E4%BB%B6-%E6%9C%89%E7%8A%B6%E6%80%81"><span class="toc-number">4.2.</span> <span class="toc-text">什么是类组件(有状态)</span></a></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E7%BB%84%E4%BB%B6%E4%B8%89%E5%A4%A7%E6%A0%B8%E5%BF%83%E5%B1%9E%E6%80%A7%E4%B9%8B%E4%B8%80-State"><span class="toc-number">5.</span> <span class="toc-text">组件三大核心属性之一: State</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#%E5%88%9D%E5%A7%8B%E5%8C%96-state"><span class="toc-number">5.1.</span> <span class="toc-text">初始化 state</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E4%BA%8B%E4%BB%B6%E7%BB%91%E5%AE%9A%E5%92%8C%E6%9B%B4%E6%94%B9-State-%E7%8A%B6%E6%80%81"><span class="toc-number">5.2.</span> <span class="toc-text">事件绑定和更改 State 状态</span></a></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E7%BB%84%E4%BB%B6%E4%B8%89%E5%A4%A7%E6%A0%B8%E5%BF%83%E5%B1%9E%E6%80%A7%E4%B9%8B%E4%B8%80-Props"><span class="toc-number">6.</span> <span class="toc-text">组件三大核心属性之一: Props</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#PropTypes-%E4%B8%BA%E7%BB%84%E4%BB%B6%E6%8F%90%E4%BE%9B%E7%B1%BB%E5%9E%8B%E6%A3%80%E6%9F%A5"><span class="toc-number">6.1.</span> <span class="toc-text">PropTypes 为组件提供类型检查</span></a></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E7%BB%84%E4%BB%B6%E4%B8%89%E5%A4%A7%E6%A0%B8%E5%BF%83%E5%B1%9E%E6%80%A7%E4%B9%8B%E4%B8%80-Refs"><span class="toc-number">7.</span> <span class="toc-text">组件三大核心属性之一: Refs</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#%E4%BD%95%E6%97%B6%E4%BD%BF%E7%94%A8-Refs"><span class="toc-number">7.1.</span> <span class="toc-text">何时使用 Refs</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E5%88%9B%E5%BB%BA-Refs"><span class="toc-number">7.2.</span> <span class="toc-text">创建 Refs</span></a></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#React-%E7%94%9F%E5%91%BD%E5%91%A8%E6%9C%9F"><span class="toc-number">8.</span> <span class="toc-text">React 生命周期</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#%E4%BB%80%E4%B9%88%E6%98%AF%E7%94%9F%E5%91%BD%E5%91%A8%E6%9C%9F"><span class="toc-number">8.1.</span> <span class="toc-text">什么是生命周期?</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#Mounting-%E6%8C%82%E8%BD%BD"><span class="toc-number">8.2.</span> <span class="toc-text">Mounting(挂载)</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#Updating-%E6%9B%B4%E6%96%B0"><span class="toc-number">8.3.</span> <span class="toc-text">Updating(更新)</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#Unmounting-%E5%8D%B8%E8%BD%BD"><span class="toc-number">8.4.</span> <span class="toc-text">Unmounting(卸载)</span></a></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#Fragments"><span class="toc-number">9.</span> <span class="toc-text">Fragments</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E7%BB%84%E4%BB%B6%E4%B9%8B%E9%97%B4%E9%80%9A%E4%BF%A1"><span class="toc-number">10.</span> <span class="toc-text">组件之间通信</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#%E2%BD%97%E7%BB%84%E4%BB%B6%E5%90%91%E2%BC%A6%E7%BB%84%E4%BB%B6%E9%80%9A%E8%AE%AF"><span class="toc-number">10.1.</span> <span class="toc-text">⽗组件向⼦组件通讯</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E2%BC%A6%E7%BB%84%E4%BB%B6%E5%90%91%E2%BD%97%E7%BB%84%E4%BB%B6%E9%80%9A%E8%AE%AF"><span class="toc-number">10.2.</span> <span class="toc-text">⼦组件向⽗组件通讯</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E5%85%84%E5%BC%9F%E7%BB%84%E4%BB%B6%E4%B8%AD%E9%80%9A%E4%BF%A1"><span class="toc-number">10.3.</span> <span class="toc-text">兄弟组件中通信</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#events-%E8%87%AA%E5%AE%9A%E4%B9%89%E4%BA%8B%E4%BB%B6%E9%80%9A%E4%BF%A1"><span class="toc-number">10.4.</span> <span class="toc-text">events 自定义事件通信</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E6%B6%88%E6%81%AF%E8%AE%A2%E9%98%85%E4%B8%8E%E5%8F%91%E5%B8%83%E6%9C%BA%E5%88%B6"><span class="toc-number">10.5.</span> <span class="toc-text">消息订阅与发布机制</span></a></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#HOOK"><span class="toc-number">11.</span> <span class="toc-text">HOOK</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#%E4%BB%80%E4%B9%88%E6%98%AF-Hook"><span class="toc-number">11.1.</span> <span class="toc-text">什么是 Hook?</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#State-Hook"><span class="toc-number">11.2.</span> <span class="toc-text">State Hook</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#Effect-Hook"><span class="toc-number">11.3.</span> <span class="toc-text">Effect Hook</span></a></li></ol></li></ol><li class="toc-item toc-level-1"><a class="toc-link" href="#Todo"><span class="toc-number"></span> <span class="toc-text">Todo</span></a></li></div></div><div class="card-widget card-recent-post"><div class="aside-list"><div class="aside-list-item no-cover"><a class="thumbnail" href="/post/a109015f.html" title="TS 中的类型验算,高级通用 API 实现"><img src="" data-lazy-src="https://ali-oss.xmwpro.com/posts/post_cover17.jpg" onerror='this.onerror=null,this.src="/img/404.jpg"' alt="TS 中的类型验算,高级通用 API 实现"></a><div class="content"><a class="title" href="/post/a109015f.html" title="TS 中的类型验算,高级通用 API 实现">TS 中的类型验算,高级通用 API 实现</a><time datetime="2023-06-26T15:26:24.000Z" title="发表于 2023-06-26 15:26:24">2023-06-26</time></div></div><div class="aside-list-item no-cover"><a class="thumbnail" href="/post/1ce87d42.html" title="使用 sort-imports 排序规则美化头部 import 代码"><img src="" data-lazy-src="https://ali-oss.xmwpro.com/posts/post_cover22.jpg" onerror='this.onerror=null,this.src="/img/404.jpg"' alt="使用 sort-imports 排序规则美化头部 import 代码"></a><div class="content"><a class="title" href="/post/1ce87d42.html" title="使用 sort-imports 排序规则美化头部 import 代码">使用 sort-imports 排序规则美化头部 import 代码</a><time datetime="2023-06-06T15:39:24.000Z" title="发表于 2023-06-06 15:39:24">2023-06-06</time></div></div><div class="aside-list-item no-cover"><a class="thumbnail" href="/post/b3e4ecaf.html" title="Vue 中如何监控用户网络状态"><img src="" data-lazy-src="https://ali-oss.xmwpro.com/posts/post_cover18.jpg" onerror='this.onerror=null,this.src="/img/404.jpg"' alt="Vue 中如何监控用户网络状态"></a><div class="content"><a class="title" href="/post/b3e4ecaf.html" title="Vue 中如何监控用户网络状态">Vue 中如何监控用户网络状态</a><time datetime="2023-05-22T16:08:02.000Z" title="发表于 2023-05-22 16:08:02">2023-05-22</time></div></div><div class="aside-list-item no-cover"><a class="thumbnail" href="/post/50b97751.html" title="在 vite 中使用 glob 实现约定式路由"><img src="" data-lazy-src="https://ali-oss.xmwpro.com/posts/post_cover43.jpg" onerror='this.onerror=null,this.src="/img/404.jpg"' alt="在 vite 中使用 glob 实现约定式路由"></a><div class="content"><a class="title" href="/post/50b97751.html" title="在 vite 中使用 glob 实现约定式路由">在 vite 中使用 glob 实现约定式路由</a><time datetime="2023-05-16T16:35:16.000Z" title="发表于 2023-05-16 16:35:16">2023-05-16</time></div></div><div class="aside-list-item no-cover"><a class="thumbnail" href="/post/7b74bd27.html" title="基于 React + Nest 的后台应用"><img src="" data-lazy-src="https://ali-oss.xmwpro.com/posts/post_cover45.jpg" onerror='this.onerror=null,this.src="/img/404.jpg"' alt="基于 React + Nest 的后台应用"></a><div class="content"><a class="title" href="/post/7b74bd27.html" title="基于 React + Nest 的后台应用">基于 React + Nest 的后台应用</a><time datetime="2023-04-18T10:39:21.000Z" title="发表于 2023-04-18 10:39:21">2023-04-18</time></div></div></div></div></div></div></main><footer id="footer"><div id="footer-wrap"><div class="site-business"><img src="" data-lazy-src="https://ali-oss.xmwpro.com/global/business.svg" alt="Cyan"></div><div class="site-services"><div class="site-services-link"><a class="site-services-link-item" href="https://www.aliyun.com/" rel="external nofollow noreferrer" target="_blank" title="阿里云提供cdn加速和云存储服务"><img src="" data-lazy-src="https://ali-oss.xmwpro.com/global/aliyun.svg" alt="阿里云"></a><a class="site-services-link-item" href="https://www.foreverblog.cn/blog/4240.html/" rel="external nofollow noreferrer" target="_blank" title="十年之约虫洞服务"><img src="" data-lazy-src="https://ali-oss.xmwpro.com/global/foreverblog-zh.svg" alt="十年之约"></a><a class="site-services-link-item" href="https://beian.miit.gov.cn/" rel="external nofollow noreferrer" target="_blank" title="粤ICP备2023007649号"><img src="" data-lazy-src="https://ali-oss.xmwpro.com/global/icp.png" alt="粤ICP备2023007649号"><span>粤ICP备2023007649号</span></a><a class="site-services-link-item" href="http://www.beian.gov.cn/portal/registerSystemInfo?recordcode=44030402006264" rel="external nofollow noreferrer" target="_blank" title="粤公网安备44030402006264号"><img src="" data-lazy-src="https://ali-oss.xmwpro.com/global/security.png" alt="粤公网安备44030402006264号"><span>粤公网安备44030402006264号</span></a></div></div><div class="footer_custom_text"><p style="margin:0"><a target="_blank" rel="noopener external nofollow noreferrer" href="https://hexo.io/" style="margin-inline:5px"><img src="" data-lazy-src="https://ali-oss.xmwpro.com/global/hexo.svg" alt="博客框架 Hexo"></a><a target="_blank" rel="noopener external nofollow noreferrer" href="https://butterfly.js.org/" style="margin-inline:5px"><img src="" data-lazy-src="https://ali-oss.xmwpro.com/global/Butterfly.svg" alt="主题 Butterfly"></a><a target="_blank" rel="noopener external nofollow noreferrer" href="https://github.com/" style="margin-inline:5px"><img src="" data-lazy-src="https://ali-oss.xmwpro.com/global/github.svg" alt="本站托管于 Github"></a><a target="_blank" rel="noopener external nofollow noreferrer" href="https://creativecommons.org/licenses/by-nc-sa/4.0/" style="margin-inline:5px"><img src="" data-lazy-src="https://ali-oss.xmwpro.com/global/copyright.svg" alt="本站采用知识共享署名-非商业性使用-相同方式共享4.0国际许可协议进行许可"></a></p></div></div></footer></div><div id="rightside"><div id="rightside-config-hide"><button id="readmode" type="button" title="阅读模式"><i class="fas fa-book-open"></i></button><button id="translateLink" type="button" title="简繁转换">繁</button><button id="darkmode" type="button" title="浅色和深色模式转换"><i class="fas fa-adjust"></i></button><button id="hide-aside-btn" type="button" title="单栏和双栏切换"><i class="fas fa-arrows-alt-h"></i></button></div><div id="rightside-config-show"><button id="rightside_config" type="button" title="设置"><i class="fas fa-cog fa-spin"></i></button><button class="close" id="mobile-toc-button" type="button" title="目录"><i class="fas fa-list-ul"></i></button><button id="to_comment" type="button" title="直达评论" onclick='cyan.scrollTo("#post-comment")'><i class="fas fa-comments"></i></button><button id="toggle-barrage" type="button" title="开启/关闭弹幕" onclick="cyan.switchCommentBarrage()"><i class="iconfont cyan-barrage"></i></button><button id="toggle-music" type="button" title="播放/暂停音乐" onclick="cyan.musicToggle()"><i class="fas fa-solid fa-music"></i></button><button id="go-up" type="button" title="回到顶部"><i class="fas fa-arrow-up"></i></button></div></div><div id="nav-music"><div id="nav-music-hoverTips" onclick="cyan.musicToggle()">播放音乐</div><meting-js id="6589687940" server="netease" type="playlist" mutex="true" preload="none" theme="var(--cyan-theme-color)" data-lrctype="0" order="random"></meting-js></div><div id="algolia-search"><div class="search-dialog"><nav class="search-nav"><span class="search-dialog-title">全局搜索</span><button class="search-close-button"><i class="fas fa-times"></i></button></nav><div class="search-wrap"><div id="algolia-search-input"></div><div id="algolia-search-results"><div id="algolia-hits"></div><div id="algolia-pagination"></div><div id="algolia-info"><div class="algolia-stats"></div><div class="algolia-poweredBy"></div></div></div></div></div><div id="search-mask"></div></div><div><script src="/js/utils.js"></script><script src="/js/main.js"></script><script src="/js/tw_cn.js"></script><script src="https://ali-oss.xmwpro.com/cdn/js/fancybox.umd.js"></script><script src="https://ali-oss.xmwpro.com/cdn/js/instantclick-1.2.2.js" type="module"></script><script src="https://ali-oss.xmwpro.com/cdn/js/lazyload.iife.min.js"></script><script src="https://ali-oss.xmwpro.com/cdn/js/snackbar.min.js"></script><script src="https://ali-oss.xmwpro.com/cdn/js/algoliasearch-lite.umd.min.js"></script><script src="https://ali-oss.xmwpro.com/cdn/js/instantsearch.production.min.js"></script><script src="/js/search/algolia.js"></script><div class="js-pjax"><script>(()=>{const o=()=>{twikoo.init(Object.assign({el:"#twikoo-wrap",envId:"https://twikoo.xmwpro.com/",region:"",onCommentLoaded:function(){btf.loadLightbox(document.querySelectorAll("#twikoo .tk-content img:not(.tk-owo-emotion)"))}},null)),GLOBAL_CONFIG_SITE.isPost&&(()=>{const o=document.getElementById("twikoo-count");o&&twikoo.getCommentsCount({envId:"https://twikoo.xmwpro.com/",region:"",urls:[window.location.pathname],includeReply:!1}).then((function(t){o.innerText=t[0].count})).catch((function(o){console.error(o)}))})()},t=()=>{"object"!=typeof twikoo?getScript("https://ali-oss.xmwpro.com/cdn/js/twikoo.all.min.js").then(o):setTimeout(o,0)};t()})()</script></div><script>window.addEventListener("load",(()=>{const e=e=>{let t="";if(e.length)for(let n=0;n<e.length;n++){t+="<div class='aside-list-item'>";{const a="data-lazy-src";t+=`<a href='${e[n].url}' class='thumbnail'><img ${a}='${e[n].avatar}' alt='${e[n].nick}'></a>`}t+=`<div class='content'>\n        <a class='comment' href='${e[n].url}' title='${e[n].content}'>${e[n].content}</a>\n        <div class='name'><span>${e[n].nick} / </span><time datetime="${e[n].date}">${btf.diffDate(e[n].date,!0)}</time></div>\n        </div></div>`}else t+="没有评论";let n=document.querySelector("#card-newest-comments .aside-list");n.innerHTML=t,window.lazyLoadInstance&&window.lazyLoadInstance.update(),window.pjax&&window.pjax.refresh(n)},t=()=>{if(document.querySelector("#card-newest-comments .aside-list")){const t=saveToLocal.get("twikoo-newest-comments");t?e(JSON.parse(t)):(()=>{const t=()=>{twikoo.getRecentComments({envId:"https://twikoo.xmwpro.com/",region:"",pageSize:6,includeReply:!0}).then((function(t){const n=t.map((e=>{return{content:(t=e.comment,""===t||(t=(t=(t=(t=t.replace(/<img.*?src="(.*?)"?[^\>]+>/gi,"[图片]")).replace(/<a[^>]+?href=["']?([^"']+)["']?[^>]*>([^<]+)<\/a>/gi,"[链接]")).replace(/<pre><code>.*?<\/pre>/gi,"[代码]")).replace(/<[^>]+>/g,"")).length>150&&(t=t.substring(0,150)+"..."),t),avatar:e.avatar,nick:e.nick,url:e.url+"#"+e.id,date:new Date(e.created).toISOString()};var t}));saveToLocal.set("twikoo-newest-comments",JSON.stringify(n),10/1440),e(n)})).catch((function(e){document.querySelector("#card-newest-comments .aside-list").innerHTML="无法获取评论，请确认相关配置是否正确"}))};"object"==typeof twikoo?t():getScript("https://ali-oss.xmwpro.com/cdn/js/twikoo.all.min.js").then(t)})()}};t(),document.addEventListener("pjax:complete",t)}))</script><script async data-pjax src="/js/custom.js"></script><script async data-pjax src="/js/cascade.js"></script><script defer data-pjax src="//at.alicdn.com/t/c/font_3348168_pqjhlyxfz9r.js"></script><script async src="/js/commentBarrage.js"></script><script async data-pjax src="/js/sky.js"></script><script src="https://sdk.51.la/perf/js-sdk-perf.min.js" crossorigin="anonymous"></script><script>LA.init({id:"JxZKIeqz3SoTqaVu",ck:"JxZKIeqz3SoTqaVu"})</script><script>(new LingQue.Monitor).init({id:"JxZKIeqz3SoTqaVu",sendSuspicious:!0})</script><script src="/cyan/random.js"></script><script>let tianliGPT_postSelector="#post #article-container",tianliGPT_key="nWP7yQwRFXvk0piPhO2w"</script><script data-pjax src="https://ali-oss.xmwpro.com/cdn/js/tianli_gpt.js"></script><link rel="stylesheet" href="https://ali-oss.xmwpro.com/cdn/css/APlayer.min.css" media="print" onload='this.media="all"'><script src="https://ali-oss.xmwpro.com/cdn/js/APlayer.min.js"></script><script src="https://ali-oss.xmwpro.com/cdn/js/Meting.min.js"></script><script src="https://ali-oss.xmwpro.com/cdn/js/pjax.min.js"></script><script>let pjaxSelectors=["head > title","#config-diff","#body-wrap","#rightside-config-hide","#rightside-config-show",".js-pjax"];var pjax=new Pjax({elements:'a:not([target="_blank"]):not([href="/tags/"]):not([href="/categories/"]):not([href="/analysis/"]):not([href="/fcircle/"])',selectors:pjaxSelectors,cacheBust:!1,analytics:!0,scrollRestoration:!1});document.addEventListener("pjax:send",(function(){if(window.tocScrollFn&&window.removeEventListener("scroll",window.tocScrollFn),window.scrollCollect&&window.removeEventListener("scroll",scrollCollect),document.getElementById("rightside").style.cssText="opacity: ''; transform: ''",window.aplayers)for(let e=0;e<window.aplayers.length;e++)window.aplayers[e].options.fixed||window.aplayers[e].destroy();"object"==typeof typed&&typed.destroy();const e=document.body.classList;e.contains("read-mode")&&e.remove("read-mode"),"object"==typeof disqusjs&&disqusjs.destroy()})),document.addEventListener("pjax:complete",(function(){window.refreshFn(),document.querySelectorAll("script[data-pjax]").forEach((e=>{const t=document.createElement("script"),o=e.text||e.textContent||e.innerHTML||"";Array.from(e.attributes).forEach((e=>t.setAttribute(e.name,e.value))),t.appendChild(document.createTextNode(o)),e.parentNode.replaceChild(t,e)})),GLOBAL_CONFIG.islazyload&&window.lazyLoadInstance.update(),"function"==typeof chatBtnFn&&chatBtnFn(),"function"==typeof panguInit&&panguInit(),"function"==typeof gtag&&gtag("config","G-2P0LMHZNDD",{page_path:window.location.pathname}),"object"==typeof _hmt&&_hmt.push(["_trackPageview",window.location.pathname]),"function"==typeof loadMeting&&document.getElementsByClassName("aplayer").length&&loadMeting(),"object"==typeof Prism&&Prism.highlightAll()})),document.addEventListener("pjax:error",(e=>{404===e.request.status&&pjax.loadUrl("/404.html")}))</script></div><script>var fdata={apiurl:"https://friend-api.xmwpro.com/",initnumber:30,stepnumber:30,error_img:"https://npm.elemecdn.com/akilar-candyassets/image/404.gif"};localStorage.setItem("fdatalist",JSON.stringify(fdata))</script><script data-pjax src="https://ali-oss.xmwpro.com/cdn/js/fetch-friend.js"></script><script data-pjax src="https://ali-oss.xmwpro.com/cdn/js/random-friends-post.js"></script><script async src="//at.alicdn.com/t/c/font_3344355_6og082zqzfd.js"></script><div class="js-pjax"><script async>for(var arr=document.getElementsByClassName("recent-post-item"),i=0;i<arr.length;i++)arr[i].classList.add("wow"),arr[i].classList.add("animate__zoomIn"),arr[i].setAttribute("data-wow-duration",""),arr[i].setAttribute("data-wow-delay",""),arr[i].setAttribute("data-wow-offset","20"),arr[i].setAttribute("data-wow-iteration","")</script><script async>for(var arr=document.getElementsByClassName("bbTimeList"),i=0;i<arr.length;i++)arr[i].classList.add("wow"),arr[i].classList.add("animate__zoomIn"),arr[i].setAttribute("data-wow-duration",""),arr[i].setAttribute("data-wow-delay",""),arr[i].setAttribute("data-wow-offset","20"),arr[i].setAttribute("data-wow-iteration","")</script><script async>for(var arr=document.getElementsByClassName("card-widget"),i=0;i<arr.length;i++)arr[i].classList.add("wow"),arr[i].classList.add("animate__zoomIn"),arr[i].setAttribute("data-wow-duration",""),arr[i].setAttribute("data-wow-delay",""),arr[i].setAttribute("data-wow-offset","20"),arr[i].setAttribute("data-wow-iteration","")</script><script async>for(var arr=document.getElementsByClassName("category-in-bar"),i=0;i<arr.length;i++)arr[i].classList.add("wow"),arr[i].classList.add("animate__zoomIn"),arr[i].setAttribute("data-wow-duration",""),arr[i].setAttribute("data-wow-delay",""),arr[i].setAttribute("data-wow-offset","20"),arr[i].setAttribute("data-wow-iteration","")</script><script async>for(var arr=document.getElementsByClassName("bber-item"),i=0;i<arr.length;i++)arr[i].classList.add("wow"),arr[i].classList.add("animate__fadeInUp"),arr[i].setAttribute("data-wow-duration","1.5s"),arr[i].setAttribute("data-wow-delay",""),arr[i].setAttribute("data-wow-offset","20"),arr[i].setAttribute("data-wow-iteration","")</script><script async>for(var arr=document.getElementsByClassName("statistics-item"),i=0;i<arr.length;i++)arr[i].classList.add("wow"),arr[i].classList.add("animate__zoomIn"),arr[i].setAttribute("data-wow-duration","1.5s"),arr[i].setAttribute("data-wow-delay",""),arr[i].setAttribute("data-wow-offset","20"),arr[i].setAttribute("data-wow-iteration","")</script></div><script defer src="https://ali-oss.xmwpro.com/cdn/js/wow.min.js"></script><script defer src="https://ali-oss.xmwpro.com/cdn/js/wow_init.js"></script><script data-pjax src="https://ali-oss.xmwpro.com/cdn/js/gitcalendar.js"></script><script data-pjax>function gitcalendar_injector_config(){document.getElementById("recent-posts").insertAdjacentHTML("afterbegin",'<div class="recent-post-item" id="gitcalendarBar" style="width:100%;height:auto;padding:10px;"><style>#git_container{min-height: 280px}@media screen and (max-width:650px) {#git_container{min-height: 0px}}</style><div id="git_loading" style="width:10%;height:100%;margin:0 auto;display: block;"><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 50 50" style="enable-background:new 0 0 50 50" xml:space="preserve"><path fill="#d0d0d0" d="M25.251,6.461c-10.318,0-18.683,8.365-18.683,18.683h4.068c0-8.071,6.543-14.615,14.615-14.615V6.461z" transform="rotate(275.098 25 25)"><animatetransform attributeType="xml" attributeName="transform" type="rotate" from="0 25 25" to="360 25 25" dur="0.6s" repeatCount="indefinite"></animatetransform></path></svg><style>#git_container{display: none;}</style></div><div id="git_container"></div></div>'),console.log("已挂载gitcalendar")}document.getElementById("recent-posts")&&"/"===location.pathname&&(gitcalendar_injector_config(),GitCalendarInit("https://github-calendar.xmwpro.com/api?Cyan-Xmw",["#e3f2fd","#bbdefb","#90caf9","#64b5f6","#42a5f5","#2196f3","#1e88e5","#1976d2","#1565c0","#0d47a1","#425AEF"],"Cyan-Xmw"))</script></body></html>